1. Discard body even if response code indicates a problem, when doing cloud backend HTTP requests. I believe this was triggering a bug in Twistd.
2. Google backend retries on 403 and other 4xx codes, not just 401.
3. More logging.
retry = False
if retry:
+ log.msg("Rescheduling failed task for retry in %d seconds." % (BACKOFF_SECONDS_BEFORE_RETRY[trynum-1],))
d = task.deferLater(self._reactor, BACKOFF_SECONDS_BEFORE_RETRY[trynum-1], operation, *args, **kwargs)
d.addErrback(self._handle_error, trynum+1, first_err_and_tb, description, operation, *args, **kwargs)
return d
# If we get an error response for which _react_to_error says we should not retry,
# raise that error even if the request was itself a retry.
+ log.msg("Giving up, no retry for %s" % (err,))
raise err.__class__, err, tb
what=what, code=response.code, phrase=response.phrase, level=log.OPERATIONAL)
if response.code < 200 or response.code >= 300:
+ response.deliverBody(Discard())
raise self.ServiceError(None, response.code,
message="unexpected response code %r %s" % (response.code, response.phrase))
from zope.interface import implements
+from allmydata.util import log
from allmydata.storage.backends.cloud.cloud_common import IContainer, \
ContainerItem, ContainerListing, CommonContainerMixin
# Generally using a task-specific thread pool is better than using
# the reactor one. However, this particular call will only run
# once an hour, so it's not likely to tie up all the threads.
- return self._deferToThread(self._credentials.refresh, httplib2.Http())
+ log.msg("Reauthenticating against Google Cloud Storage.")
+ def finished(result):
+ log.msg("Done reauthenticating against Google Cloud Storage.")
+ return result
+ d = self._deferToThread(self._credentials.refresh, httplib2.Http())
+ d.addBoth(finished)
+ return d
return self._lock.run(run)
def get_authorization_header(self):
self._project_id = project_id # Only need for bucket creation/deletion
def _react_to_error(self, response_code):
- if response_code == UNAUTHORIZED:
+ if response_code >= 400 and response_code < 500:
+ # Unauthorized/forbidden/etc. we should retry, eventually we will
+ # reauthenticate:
return True
else:
return CommonContainerMixin._react_to_error(self, response_code)
third.callback(done)
self.assertEqual(result, [done])
+ def test_react_to_error(self):
+ """
+ GoogleStorageContainer._react_to_error() will return True (i.e. retry)
+ for any response code between 400 and 599.
+ """
+ self.assertFalse(self.container._react_to_error(399))
+ self.assertFalse(self.container._react_to_error(600))
+ for i in range(400, 600):
+ self.assertTrue(self.container._react_to_error(i))
+
def test_head_object(self):
"""
GoogleStorageContainer.head_object() sends the appropriate HTTP