# HG changeset patch # User Pierre-Yves David # Date 2020-11-28 18:58:37 # Node ID 57183111a463924c0196253342048b052a17e83c # Parent 971424517e17cad2dc00fe140627a26ec3de49c2 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 diff --git a/hgext/phabricator.py b/hgext/phabricator.py --- a/hgext/phabricator.py +++ b/hgext/phabricator.py @@ -35,6 +35,14 @@ Config:: # 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 json 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( ) 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 @@ def callconduit(ui, name, params): 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)