32 # curl command to use. If not set (default), use builtin HTTP library to |
32 # curl command to use. If not set (default), use builtin HTTP library to |
33 # communicate. If set, use the specified curl command. This could be useful |
33 # communicate. If set, use the specified curl command. This could be useful |
34 # if you need to specify advanced options that is not easily supported by |
34 # if you need to specify advanced options that is not easily supported by |
35 # the internal library. |
35 # the internal library. |
36 curlcmd = curl --connect-timeout 2 --retry 3 --silent |
36 curlcmd = curl --connect-timeout 2 --retry 3 --silent |
|
37 |
|
38 # retry failed command N time (default 0). Useful when using the extension |
|
39 # over flakly connection. |
|
40 # |
|
41 # We wait `retry.interval` between each retry, in seconds. |
|
42 # (default 1 second). |
|
43 retry = 3 |
|
44 retry.interval = 10 |
37 |
45 |
38 [auth] |
46 [auth] |
39 example.schemes = https |
47 example.schemes = https |
40 example.prefix = phab.example.com |
48 example.prefix = phab.example.com |
41 |
49 |
51 import itertools |
59 import itertools |
52 import json |
60 import json |
53 import mimetypes |
61 import mimetypes |
54 import operator |
62 import operator |
55 import re |
63 import re |
|
64 import time |
56 |
65 |
57 from mercurial.node import bin, nullid, short |
66 from mercurial.node import bin, nullid, short |
58 from mercurial.i18n import _ |
67 from mercurial.i18n import _ |
59 from mercurial.pycompat import getattr |
68 from mercurial.pycompat import getattr |
60 from mercurial.thirdparty import attr |
69 from mercurial.thirdparty import attr |
398 sin.close() |
417 sin.close() |
399 body = sout.read() |
418 body = sout.read() |
400 else: |
419 else: |
401 urlopener = urlmod.opener(ui, authinfo) |
420 urlopener = urlmod.opener(ui, authinfo) |
402 request = util.urlreq.request(pycompat.strurl(url), data=data) |
421 request = util.urlreq.request(pycompat.strurl(url), data=data) |
403 with contextlib.closing(urlopener.open(request)) as rsp: |
422 max_try = ui.configint(b'phabricator', b'retry') + 1 |
404 body = rsp.read() |
423 for try_count in range(max_try): |
|
424 try: |
|
425 with contextlib.closing(urlopener.open(request)) as rsp: |
|
426 body = rsp.read() |
|
427 break |
|
428 except util.urlerr.urlerror as err: |
|
429 if try_count == max_try - 1: |
|
430 raise |
|
431 ui.debug( |
|
432 b'Conduit Request failed (try %d/%d): %r\n' |
|
433 % (try_count + 1, max_try, err) |
|
434 ) |
|
435 # failing request might come from overloaded server |
|
436 retry_interval = ui.configint(b'phabricator', b'retry.interval') |
|
437 time.sleep(retry_interval) |
405 ui.debug(b'Conduit Response: %s\n' % body) |
438 ui.debug(b'Conduit Response: %s\n' % body) |
406 parsed = pycompat.rapply( |
439 parsed = pycompat.rapply( |
407 lambda x: encoding.unitolocal(x) |
440 lambda x: encoding.unitolocal(x) |
408 if isinstance(x, pycompat.unicode) |
441 if isinstance(x, pycompat.unicode) |
409 else x, |
442 else x, |