← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~pappacena/launchpad:mirror-prober-timeout-after-response into launchpad:master

 

Thiago F. Pappacena has proposed merging ~pappacena/launchpad:mirror-prober-timeout-after-response into launchpad:master.

Commit message:
Avoiding AlreadyCalledError caused by race condition between timeout and real response

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/393919
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~pappacena/launchpad:mirror-prober-timeout-after-response into launchpad:master.
diff --git a/lib/lp/registry/scripts/distributionmirror_prober.py b/lib/lp/registry/scripts/distributionmirror_prober.py
index 0ed5eb9..ca6c4d0 100644
--- a/lib/lp/registry/scripts/distributionmirror_prober.py
+++ b/lib/lp/registry/scripts/distributionmirror_prober.py
@@ -401,6 +401,12 @@ class ProberFactory(protocol.ClientFactory):
         self._deferred.callback(status)
 
     def failed(self, reason):
+        if isinstance(reason, ProberTimeout) and self._deferred.called:
+            msg = (
+                "Prober %s for url %s tried to fail with timeout after it has "
+                "already received a response.")
+            self.logger.info(msg, self, self.url)
+            return
         self._deferred.errback(reason)
 
     def _cancelTimeout(self, result):
diff --git a/lib/lp/registry/tests/test_distributionmirror_prober.py b/lib/lp/registry/tests/test_distributionmirror_prober.py
index 38bf7dd..6e33f59 100644
--- a/lib/lp/registry/tests/test_distributionmirror_prober.py
+++ b/lib/lp/registry/tests/test_distributionmirror_prober.py
@@ -5,7 +5,6 @@
 
 __metaclass__ = type
 
-
 from datetime import datetime
 import logging
 import os
@@ -200,6 +199,15 @@ class TestProberHTTPSProtocolAndFactory(TestCase):
         d = self._createProberAndProbe(self.urls['404'])
         return assert_fails_with(d, BadResponseCode)
 
+    def test_multiple_failures(self):
+        """TAvoid defer.AlreadyCalledError when failWithTimeoutError is still
+        scheduled after we already have the HTTP response.
+        """
+        prober = ProberFactory(self.urls['500'])
+        d = prober.probe()
+        reactor.callLater(0, prober.failWithTimeoutError)
+        return assert_fails_with(d, BadResponseCode)
+
     def test_config_no_https_proxy(self):
         prober = ProberFactory(self.urls['200'])
         self.assertThat(prober, MatchesStructure.byEquality(