[CalendarServer-changes] [4800] CalendarServer/branches/users/cdaboo/deployment-partition-4722

source_changes at macosforge.org source_changes at macosforge.org
Mon Nov 23 12:46:38 PST 2009


Revision: 4800
          http://trac.macosforge.org/projects/calendarserver/changeset/4800
Author:   cdaboo at apple.com
Date:     2009-11-23 12:46:35 -0800 (Mon, 23 Nov 2009)
Log Message:
-----------
Fixing up client pool error handling.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/deployment-partition-4722/twistedcaldav/client/pool.py

Added Paths:
-----------
    CalendarServer/branches/users/cdaboo/deployment-partition-4722/lib-patches/Twisted/twisted.web2.client.http.patch

Added: CalendarServer/branches/users/cdaboo/deployment-partition-4722/lib-patches/Twisted/twisted.web2.client.http.patch
===================================================================
--- CalendarServer/branches/users/cdaboo/deployment-partition-4722/lib-patches/Twisted/twisted.web2.client.http.patch	                        (rev 0)
+++ CalendarServer/branches/users/cdaboo/deployment-partition-4722/lib-patches/Twisted/twisted.web2.client.http.patch	2009-11-23 20:46:35 UTC (rev 4800)
@@ -0,0 +1,14 @@
+Index: twisted/web2/client/http.py
+===================================================================
+--- twisted/web2/client/http.py	(revision 19773)
++++ twisted/web2/client/http.py	(working copy)
+@@ -134,8 +134,7 @@
+         self.responseDefer.errback(ProtocolError(text))
+ 
+     def connectionLost(self, reason):
+-        ### FIXME!
+-        pass
++        self._error(reason)
+     
+     def gotInitialLine(self, initialLine):
+         parts = initialLine.split(' ', 2)

Modified: CalendarServer/branches/users/cdaboo/deployment-partition-4722/twistedcaldav/client/pool.py
===================================================================
--- CalendarServer/branches/users/cdaboo/deployment-partition-4722/twistedcaldav/client/pool.py	2009-11-23 19:21:36 UTC (rev 4799)
+++ CalendarServer/branches/users/cdaboo/deployment-partition-4722/twistedcaldav/client/pool.py	2009-11-23 20:46:35 UTC (rev 4800)
@@ -21,8 +21,8 @@
 ]
 
 from twisted.internet.address import IPv4Address
-from twisted.internet.defer import Deferred
-from twisted.internet.protocol import ReconnectingClientFactory
+from twisted.internet.defer import Deferred, inlineCallbacks, returnValue
+from twisted.internet.protocol import ClientFactory
 from twisted.internet.ssl import DefaultOpenSSLContextFactory
 from twisted.web2 import responsecode
 from twisted.web2.client.http import HTTPClientProtocol
@@ -31,17 +31,17 @@
 import OpenSSL
 import urlparse
 
-class ReverseProxyClientFactory(ReconnectingClientFactory, LoggingMixIn):
+class ReverseProxyClientFactory(ClientFactory, LoggingMixIn):
     """
-    A client factory for HTTPClient that notifies a pool of it's state.
+    A client factory for HTTPClient that notifies a pool of it's state. It the connection
+    fails in the middle of a request it will retry the request.
 
-    @ivar connectionPool: A managing connection pool that we notify of events.
     @ivar protocol: The current instance of our protocol that we pass
         to our connectionPool.
+    @ivar connectionPool: A managing connection pool that we notify of events.
     """
     protocol = HTTPClientProtocol
     connectionPool = None
-    maxRetries = 2
 
     def __init__(self, reactor):
         self.reactor = reactor
@@ -98,6 +98,7 @@
         progress.
     """
     clientFactory = ReverseProxyClientFactory
+    maxRetries = 2
 
     def __init__(self, scheme, serverAddress, maxClients=5, reactor=None):
         """
@@ -200,6 +201,7 @@
         d.addCallback(_freeClientAfterRequest)
         return d
 
+    @inlineCallbacks
     def submitRequest(self, request, *args, **kwargs):
         """
         Select an available client and perform the given request on it.
@@ -214,6 +216,33 @@
         @return: A L{Deferred} that fires with the result of the given command.
         """
 
+        # Try this maxRetries times
+        for ctr in xrange(self.maxRetries + 1):
+            try:
+                response = yield self._submitRequest(request, args, kwargs)
+            except Exception, e:
+                self.log_error("ReverseProxy connection error (attempt: %d) - retrying: %s" % (ctr+1, e,))
+                continue
+            else:
+                returnValue(response)
+        else:
+            self.log_error("ReverseProxy connection error - exhausted retry attempts: %s" % (e,))
+            raise HTTPError(StatusResponse(responsecode.BAD_GATEWAY, "Could not connect to reverse proxy host."))
+
+    def _submitRequest(self, request, *args, **kwargs):
+        """
+        Select an available client and perform the given request on it.
+
+        @param command: A C{str} representing an attribute of
+            L{MemCacheProtocol}.
+        @parma args: Any positional arguments that should be passed to
+            C{command}.
+        @param kwargs: Any keyword arguments that should be passed to
+            C{command}.
+
+        @return: A L{Deferred} that fires with the result of the given command.
+        """
+
         client = None
         if len(self._freeClients) > 0:
             client = self._freeClients.pop()
@@ -227,8 +256,12 @@
             self._logClientStats()
 
         else:
+            def _badGateway(f):
+                raise HTTPError(StatusResponse(responsecode.BAD_GATEWAY, "Could not connect to reverse proxy host."))
+
             d = self._newClientConnection()
             d.addCallback(self._performRequestOnClient, request, *args, **kwargs)
+            d.addErrback(_badGateway)
 
         return d
 
@@ -255,6 +288,8 @@
         self.log_debug("Removed client: %r" % (client,))
         self._logClientStats()
 
+        self._processPending()
+
     def clientBusy(self, client):
         """
         Notify that the given client is being used to complete a request.
@@ -284,6 +319,12 @@
         if self.shutdown_deferred and self._isIdle():
             self.shutdown_deferred.callback(None)
 
+        self.log_debug("Freed client: %r" % (client,))
+        self._logClientStats()
+
+        self._processPending()
+
+    def _processPending(self):
         if len(self._pendingRequests) > 0:
             d, request, args, kwargs = self._pendingRequests.pop(0)
 
@@ -291,13 +332,11 @@
                     request, args, kwargs))
             self._logClientStats()
 
-            _ign_d = self.submitRequest(request, *args, **kwargs)
+            _ign_d = self._submitRequest(request, *args, **kwargs)
 
             _ign_d.addCallback(d.callback)
+            _ign_d.addErrback(d.errback)
 
-        self.log_debug("Freed client: %r" % (client,))
-        self._logClientStats()
-
     def suggestMaxClients(self, maxClients):
         """
         Suggest the maximum number of concurrently connected clients.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20091123/b56e15d9/attachment-0001.html>


More information about the calendarserver-changes mailing list