obsexchange: fallback to simpler request for dumb http server stable
authorPierre-Yves David <pierre-yves.david@octobus.net>
Fri, 06 Mar 2020 02:42:03 +0100
branchstable
changeset 5202 c0b8804066dc
parent 5201 7c6d08cd1221
child 5205 240efc3ab4dd
obsexchange: fallback to simpler request for dumb http server If the http server cannot accept many arguments, avoid sending too large requests (at the cost of more data exchanged). A better solution would be to aggregate contiguous range, but this is a question for later.
CHANGELOG
hgext3rd/evolve/obsdiscovery.py
hgext3rd/evolve/obsexchange.py
--- a/CHANGELOG	Fri Mar 06 02:46:51 2020 +0100
+++ b/CHANGELOG	Fri Mar 06 02:42:03 2020 +0100
@@ -1,6 +1,11 @@
 Changelog
 =========
 
+9.3.0 - in progress
+-------------------
+
+  * obsexchange: avoid sending too large request to http server
+
 9.3.0 -- 2020-03-04
 -------------------
 
--- a/hgext3rd/evolve/obsdiscovery.py	Fri Mar 06 02:46:51 2020 +0100
+++ b/hgext3rd/evolve/obsdiscovery.py	Fri Mar 06 02:42:03 2020 +0100
@@ -866,6 +866,12 @@
                   % len(revs))
         missing = findmissingrange(repo.ui, repo, pullop.remote, revs)
         boundaries[b'missing'] = missing
+        # using getattr since `limitedarguments` is missing
+        # hg <= 5.0 (69921d02daaf)
+        if getattr(pullop.remote, 'limitedarguments', False):
+            # prepare for a possible fallback to common
+            common = repo.set("heads(only(%ld, %ln))", revs, missing)
+            boundaries[b'common'] = [c.node() for c in common]
     else:
         boundaries[b'common'] = [node.nullid]
     return boundaries
--- a/hgext3rd/evolve/obsexchange.py	Fri Mar 06 02:46:51 2020 +0100
+++ b/hgext3rd/evolve/obsexchange.py	Fri Mar 06 02:42:03 2020 +0100
@@ -54,6 +54,18 @@
     gboptsmap[b'evo_obscommon'] = b'nodes'
     gboptsmap[b'evo_missing_nodes'] = b'nodes'
 
+ARGUMENTS_LIMIT = 200
+
+OVERFLOW_MSG = """obsmarkers differ for %d common nodes
+|
+| This might be too much for the remote HTTP server that doesn't accept
+| arguments through POST request. (config: experimental.httppostargs=yes)
+|
+| Falling back to a less efficient fetching method.
+|
+| More efficient fetching method is possible and will be used in the future.
+"""
+
 @eh.wrapfunction(exchange, '_pullbundle2extraprepare')
 def _addobscommontob2pull(orig, pullop, kwargs):
     ret = orig(pullop, kwargs)
@@ -61,13 +73,22 @@
     if (b'obsmarkers' in kwargs
         and pullop.remote.capable(b'_evoext_getbundle_obscommon')):
         boundaries = obsdiscovery.buildpullobsmarkersboundaries(pullop)
+        use_common = True
         if b'missing' in boundaries:
+            use_common = False
             missing = boundaries[b'missing']
-            if missing:
-                obsexcmsg(ui, b'request obsmarkers for %d common nodes\n'
-                          % len(missing))
-            kwargs[b'evo_missing_nodes'] = missing
-        elif b'common' in boundaries:
+            # using getattr since `limitedarguments` is missing
+            # hg <= 5.0 (69921d02daaf)
+            limitedarguments = getattr(pullop.remote, 'limitedarguments', False)
+            if limitedarguments and len(missing) > ARGUMENTS_LIMIT:
+                obsexcmsg(ui, OVERFLOW_MSG % len(missing))
+                use_common = True
+            else:
+                if missing:
+                    obsexcmsg(ui, b'request obsmarkers for %d common nodes\n'
+                              % len(missing))
+                kwargs[b'evo_missing_nodes'] = missing
+        if use_common and b'common' in boundaries:
             common = boundaries[b'common']
             if common != pullop.common:
                 obsexcmsg(ui, b'request obsmarkers for some common nodes\n')