robustcheckout: factor network failure handling into own function (bug 1317594); r?glob draft
authorGregory Szorc <gps@mozilla.com>
Mon, 10 Apr 2017 13:35:28 -0700
changeset 10754 40e0c55de0e5a11142cb99a5f8eceb654db5b760
parent 10753 7c3f3c6bdb2f84b3c07d3841d7e05cfd2f078875
child 10755 209c4529830574a9c5287c9b5dff5e4e43a4b1c5
push id1617
push userbmo:gps@mozilla.com
push dateMon, 10 Apr 2017 21:00:30 +0000
reviewersglob
bugs1317594
robustcheckout: factor network failure handling into own function (bug 1317594); r?glob We're going to introduce another consumer. Let's make the code easier to call. MozReview-Commit-ID: 6Zx59um4XiX
hgext/robustcheckout/__init__.py
--- a/hgext/robustcheckout/__init__.py
+++ b/hgext/robustcheckout/__init__.py
@@ -221,51 +221,54 @@ def _docheckout(ui, url, dest, upstream,
             ui.warn('(attempting checkout from beginning)\n')
             return callself()
 
         raise
 
     # At this point we either have an existing working directory using
     # shared, pooled storage or we have nothing.
 
+    def handlenetworkfailure():
+        if networkattempts[0] >= networkattemptlimit:
+            raise error.Abort('reached maximum number of network attempts; '
+                              'giving up\n')
+
+        ui.warn('(retrying after network failure on attempt %d of %d)\n' %
+                (networkattempts[0], networkattemptlimit))
+
+        # Do a backoff on retries to mitigate the thundering herd
+        # problem. This is an exponential backoff with a multipler
+        # plus random jitter thrown in for good measure.
+        # With the default settings, backoffs will be:
+        # 1) 2.5 - 6.5
+        # 2) 5.5 - 9.5
+        # 3) 11.5 - 15.5
+        backoff = (2 ** networkattempts[0] - 1) * 1.5
+        jittermin = ui.configint('robustcheckout', 'retryjittermin', 1000)
+        jittermax = ui.configint('robustcheckout', 'retryjittermax', 5000)
+        backoff += float(random.randint(jittermin, jittermax)) / 1000.0
+        ui.warn('(waiting %.2fs before retry)\n' % backoff)
+        time.sleep(backoff)
+
+        networkattempts[0] += 1
+
     def handlepullabort(e):
         """Handle an error.Abort raised during a pull.
 
         Returns True if caller should call ``callself()`` to retry.
         """
         if e.args[0] == _('repository is unrelated'):
             ui.warn('(repository is unrelated; deleting)\n')
             destvfs.rmtree(forcibly=True)
             return True
         elif e.args[0].startswith(_('stream ended unexpectedly')):
             ui.warn('%s\n' % e.args[0])
-            if networkattempts[0] < networkattemptlimit:
-                ui.warn('(retrying after network failure on attempt %d of %d)\n' %
-                        (networkattempts[0], networkattemptlimit))
-
-                # Do a backoff on retries to mitigate the thundering herd
-                # problem. This is an exponential backoff with a multipler
-                # plus random jitter thrown in for good measure.
-                # With the default settings, backoffs will be:
-                # 1) 2.5 - 6.5
-                # 2) 5.5 - 9.5
-                # 3) 11.5 - 15.5
-                backoff = (2 ** networkattempts[0] - 1) * 1.5
-                jittermin = ui.configint('robustcheckout', 'retryjittermin', 1000)
-                jittermax = ui.configint('robustcheckout', 'retryjittermax', 5000)
-                backoff += float(random.randint(jittermin, jittermax)) / 1000.0
-                ui.warn('(waiting %.2fs before retry)\n' % backoff)
-                time.sleep(backoff)
-
-                networkattempts[0] += 1
-
-                return True
-            else:
-                raise error.Abort('reached maximum number of network attempts; '
-                                  'giving up\n')
+            # Will raise if failure limit reached.
+            handlenetworkfailure()
+            return True
 
         return False
 
     created = False
 
     if not destvfs.exists():
         # Ensure parent directories of destination exist.
         # Mercurial 3.8 removed ensuredirs and made makedirs race safe.