phabricator: introduce a `phabricator.retry` option
For the past 2 days, my connection to phab.mercurial-scm.org became extremely
poor. In practice this mean that any conduit call has a fairly high change to
hang and die. Giving the amount of call done by the phabricator extension, it
means the when I am lucky I can get 1 or 2 Diff to update after a few try, but
anything sizeable doesn't have any hope to get through.
This changesets introduce a new option for the fabricator extension to try retry
failed command itself. So that I can get Diff through.
As you can guess, this changeset managed to reach Phabricator thanks to itself.
Differential Revision: https://phab.mercurial-scm.org/D9449
--- a/hgext/phabricator.py Tue Nov 24 16:17:16 2020 -0500
+++ b/hgext/phabricator.py Sat Nov 28 19:58:37 2020 +0100
@@ -35,6 +35,14 @@
# the internal library.
curlcmd = curl --connect-timeout 2 --retry 3 --silent
+ # retry failed command N time (default 0). Useful when using the extension
+ # over flakly connection.
+ #
+ # We wait `retry.interval` between each retry, in seconds.
+ # (default 1 second).
+ retry = 3
+ retry.interval = 10
+
[auth]
example.schemes = https
example.prefix = phab.example.com
@@ -53,6 +61,7 @@
import mimetypes
import operator
import re
+import time
from mercurial.node import bin, nullid, short
from mercurial.i18n import _
@@ -136,6 +145,16 @@
)
eh.configitem(
b'phabricator',
+ b'retry',
+ default=0,
+)
+eh.configitem(
+ b'phabricator',
+ b'retry.interval',
+ default=1,
+)
+eh.configitem(
+ b'phabricator',
b'url',
default=None,
)
@@ -400,8 +419,22 @@
else:
urlopener = urlmod.opener(ui, authinfo)
request = util.urlreq.request(pycompat.strurl(url), data=data)
- with contextlib.closing(urlopener.open(request)) as rsp:
- body = rsp.read()
+ max_try = ui.configint(b'phabricator', b'retry') + 1
+ for try_count in range(max_try):
+ try:
+ with contextlib.closing(urlopener.open(request)) as rsp:
+ body = rsp.read()
+ break
+ except util.urlerr.urlerror as err:
+ if try_count == max_try - 1:
+ raise
+ ui.debug(
+ b'Conduit Request failed (try %d/%d): %r\n'
+ % (try_count + 1, max_try, err)
+ )
+ # failing request might come from overloaded server
+ retry_interval = ui.configint(b'phabricator', b'retry.interval')
+ time.sleep(retry_interval)
ui.debug(b'Conduit Response: %s\n' % body)
parsed = pycompat.rapply(
lambda x: encoding.unitolocal(x)