##// END OF EJS Templates
pyro4: Create pyro proxy factory which returns instaces scoped by the request.
Martin Bornhold -
r341:5b26b74b default
parent child Browse files
Show More
@@ -64,11 +64,11 b' def connect_pyro4(server_and_port):'
64 64 from rhodecode.lib.vcs import connection, client
65 65 from rhodecode.lib.middleware.utils import scm_app
66 66
67 git_remote = client.ThreadlocalProxyFactory(
67 git_remote = client.RequestScopeProxyFactory(
68 68 settings.pyro_remote(settings.PYRO_GIT, server_and_port))
69 hg_remote = client.ThreadlocalProxyFactory(
69 hg_remote = client.RequestScopeProxyFactory(
70 70 settings.pyro_remote(settings.PYRO_HG, server_and_port))
71 svn_remote = client.ThreadlocalProxyFactory(
71 svn_remote = client.RequestScopeProxyFactory(
72 72 settings.pyro_remote(settings.PYRO_SVN, server_and_port))
73 73
74 74 connection.Git = client.RepoMaker(proxy_factory=git_remote)
@@ -34,6 +34,7 b' from urllib2 import URLError'
34 34 import msgpack
35 35 import Pyro4
36 36 import requests
37 from pyramid.threadlocal import get_current_request
37 38 from Pyro4.errors import CommunicationError, ConnectionClosedError, DaemonError
38 39
39 40 from rhodecode.lib.vcs import exceptions
@@ -190,19 +191,61 b' class RepoMaker(object):'
190 191 return _wrap_remote_call(remote_proxy, func)
191 192
192 193
193 class ThreadlocalProxyFactory(object):
194 class RequestScopeProxyFactory(object):
194 195 """
195 Creates one Pyro4 proxy per thread on demand.
196 This factory returns pyro proxy instances based on a per request scope.
197 It returns the same instance if called from within the same request and
198 different instances if called from different requests.
196 199 """
197 200
198 201 def __init__(self, remote_uri):
199 202 self._remote_uri = remote_uri
200 self._thread_local = threading.local()
203 self._proxy_pool = []
204 self._borrowed_proxies = {}
205
206 def __call__(self, request=None):
207 """
208 Wrapper around `getProxy`.
209 """
210 request = request or get_current_request()
211 return self.getProxy(request)
212
213 def getProxy(self, request=None):
214 """
215 Call this to get the pyro proxy instance for the request.
216 """
217 request = request or get_current_request()
218
219 # Return already borrowed proxy for this request
220 if request in self._borrowed_proxies:
221 return self._borrowed_proxies[request]
201 222
202 def __call__(self):
203 if not hasattr(self._thread_local, 'proxy'):
204 self._thread_local.proxy = Pyro4.Proxy(self._remote_uri)
205 return self._thread_local.proxy
223 # Get proxy from pool or create new instance.
224 try:
225 proxy = self._proxy_pool.pop()
226 except IndexError:
227 log.info('Creating new proxy for remote_uri=%s', self._remote_uri)
228 proxy = Pyro4.Proxy(self._remote_uri)
229
230 # Store proxy instance as borrowed and add request callback.
231 self._borrowed_proxies[request] = proxy
232 request.add_finished_callback(self._returnProxy)
233
234 return proxy
235
236 def _returnProxy(self, request=None):
237 """
238 Callback that gets called by pyramid when the request is finished.
239 It puts the proxy back into the pool.
240 """
241 request = request or get_current_request()
242
243 if request in self._borrowed_proxies:
244 proxy = self._borrowed_proxies.pop(request)
245 self._proxy_pool.append(proxy)
246 else:
247 log.warn('Return proxy for remote_uri=%s but no proxy borrowed '
248 'for this request.', self._remote_uri)
206 249
207 250
208 251 class RemoteRepo(object):
General Comments 0
You need to be logged in to leave comments. Login now