diff --git a/hgext/phabricator.py b/hgext/phabricator.py --- a/hgext/phabricator.py +++ b/hgext/phabricator.py @@ -35,6 +35,19 @@ # 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 (default 1) + retry = 3 + retry.interval = 10 + + # the retry option can combine well with the http.timeout one. + # + # For example to give up on http request after 20 seconds: + [http] + timeout=20 + [auth] example.schemes = https example.prefix = phab.example.com @@ -53,6 +66,7 @@ import mimetypes import operator import re +import time from mercurial.node import bin, nullid, short from mercurial.i18n import _ @@ -136,6 +150,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 +424,20 @@ 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: + 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)