##// 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 from rhodecode.lib.vcs import connection, client
64 from rhodecode.lib.vcs import connection, client
65 from rhodecode.lib.middleware.utils import scm_app
65 from rhodecode.lib.middleware.utils import scm_app
66
66
67 git_remote = client.ThreadlocalProxyFactory(
67 git_remote = client.RequestScopeProxyFactory(
68 settings.pyro_remote(settings.PYRO_GIT, server_and_port))
68 settings.pyro_remote(settings.PYRO_GIT, server_and_port))
69 hg_remote = client.ThreadlocalProxyFactory(
69 hg_remote = client.RequestScopeProxyFactory(
70 settings.pyro_remote(settings.PYRO_HG, server_and_port))
70 settings.pyro_remote(settings.PYRO_HG, server_and_port))
71 svn_remote = client.ThreadlocalProxyFactory(
71 svn_remote = client.RequestScopeProxyFactory(
72 settings.pyro_remote(settings.PYRO_SVN, server_and_port))
72 settings.pyro_remote(settings.PYRO_SVN, server_and_port))
73
73
74 connection.Git = client.RepoMaker(proxy_factory=git_remote)
74 connection.Git = client.RepoMaker(proxy_factory=git_remote)
@@ -34,6 +34,7 b' from urllib2 import URLError'
34 import msgpack
34 import msgpack
35 import Pyro4
35 import Pyro4
36 import requests
36 import requests
37 from pyramid.threadlocal import get_current_request
37 from Pyro4.errors import CommunicationError, ConnectionClosedError, DaemonError
38 from Pyro4.errors import CommunicationError, ConnectionClosedError, DaemonError
38
39
39 from rhodecode.lib.vcs import exceptions
40 from rhodecode.lib.vcs import exceptions
@@ -190,19 +191,61 b' class RepoMaker(object):'
190 return _wrap_remote_call(remote_proxy, func)
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 def __init__(self, remote_uri):
201 def __init__(self, remote_uri):
199 self._remote_uri = remote_uri
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):
223 # Get proxy from pool or create new instance.
203 if not hasattr(self._thread_local, 'proxy'):
224 try:
204 self._thread_local.proxy = Pyro4.Proxy(self._remote_uri)
225 proxy = self._proxy_pool.pop()
205 return self._thread_local.proxy
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 class RemoteRepo(object):
251 class RemoteRepo(object):
General Comments 0
You need to be logged in to leave comments. Login now