Mercurial > hg
comparison mercurial/wireprotov1peer.py @ 37633:33a6eee08db2
wireproto: remove iterbatch() from peer interface (API)
Good riddance.
Some tests have been ported to the new API. This probably should
have been done in earlier commits. But duplicating the test coverage
would have been difficult. It was easier this way.
.. api::
The wire protocol peer's ``iterbatch()`` for bulk executing commands
has been remove.d Use ``peer.commandexecutor()`` instead.
Differential Revision: https://phab.mercurial-scm.org/D3271
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Wed, 11 Apr 2018 16:18:26 -0700 |
parents | 2f626233859b |
children | cc8c06835097 |
comparison
equal
deleted
inserted
replaced
37632:6c55ce51d6c3 | 37633:33a6eee08db2 |
---|---|
71 def set(self, value): | 71 def set(self, value): |
72 if util.safehasattr(self, 'value'): | 72 if util.safehasattr(self, 'value'): |
73 raise error.RepoError("future is already set") | 73 raise error.RepoError("future is already set") |
74 self.value = value | 74 self.value = value |
75 | 75 |
76 class batcher(object): | |
77 '''base class for batches of commands submittable in a single request | |
78 | |
79 All methods invoked on instances of this class are simply queued and | |
80 return a a future for the result. Once you call submit(), all the queued | |
81 calls are performed and the results set in their respective futures. | |
82 ''' | |
83 def __init__(self): | |
84 self.calls = [] | |
85 def __getattr__(self, name): | |
86 def call(*args, **opts): | |
87 resref = future() | |
88 # Please don't invent non-ascii method names, or you will | |
89 # give core hg a very sad time. | |
90 self.calls.append((name.encode('ascii'), args, opts, resref,)) | |
91 return resref | |
92 return call | |
93 def submit(self): | |
94 raise NotImplementedError() | |
95 | |
96 class iterbatcher(batcher): | |
97 | |
98 def submit(self): | |
99 raise NotImplementedError() | |
100 | |
101 def results(self): | |
102 raise NotImplementedError() | |
103 | |
104 class remoteiterbatcher(iterbatcher): | |
105 def __init__(self, remote): | |
106 super(remoteiterbatcher, self).__init__() | |
107 self._remote = remote | |
108 | |
109 def __getattr__(self, name): | |
110 # Validate this method is batchable, since submit() only supports | |
111 # batchable methods. | |
112 fn = getattr(self._remote, name) | |
113 if not getattr(fn, 'batchable', None): | |
114 raise error.ProgrammingError('Attempted to batch a non-batchable ' | |
115 'call to %r' % name) | |
116 | |
117 return super(remoteiterbatcher, self).__getattr__(name) | |
118 | |
119 def submit(self): | |
120 """Break the batch request into many patch calls and pipeline them. | |
121 | |
122 This is mostly valuable over http where request sizes can be | |
123 limited, but can be used in other places as well. | |
124 """ | |
125 # 2-tuple of (command, arguments) that represents what will be | |
126 # sent over the wire. | |
127 requests = [] | |
128 | |
129 # 4-tuple of (command, final future, @batchable generator, remote | |
130 # future). | |
131 results = [] | |
132 | |
133 for command, args, opts, finalfuture in self.calls: | |
134 mtd = getattr(self._remote, command) | |
135 batchable = mtd.batchable(mtd.__self__, *args, **opts) | |
136 | |
137 commandargs, fremote = next(batchable) | |
138 assert fremote | |
139 requests.append((command, commandargs)) | |
140 results.append((command, finalfuture, batchable, fremote)) | |
141 | |
142 if requests: | |
143 self._resultiter = self._remote._submitbatch(requests) | |
144 | |
145 self._results = results | |
146 | |
147 def results(self): | |
148 for command, finalfuture, batchable, remotefuture in self._results: | |
149 # Get the raw result, set it in the remote future, feed it | |
150 # back into the @batchable generator so it can be decoded, and | |
151 # set the result on the final future to this value. | |
152 remoteresult = next(self._resultiter) | |
153 remotefuture.set(remoteresult) | |
154 finalfuture.set(next(batchable)) | |
155 | |
156 # Verify our @batchable generators only emit 2 values. | |
157 try: | |
158 next(batchable) | |
159 except StopIteration: | |
160 pass | |
161 else: | |
162 raise error.ProgrammingError('%s @batchable generator emitted ' | |
163 'unexpected value count' % command) | |
164 | |
165 yield finalfuture.value | |
166 | |
167 def encodebatchcmds(req): | 76 def encodebatchcmds(req): |
168 """Return a ``cmds`` argument value for the ``batch`` command.""" | 77 """Return a ``cmds`` argument value for the ``batch`` command.""" |
169 escapearg = wireprototypes.escapebatcharg | 78 escapearg = wireprototypes.escapebatcharg |
170 | 79 |
171 cmds = [] | 80 cmds = [] |
409 """ | 318 """ |
410 def commandexecutor(self): | 319 def commandexecutor(self): |
411 return peerexecutor(self) | 320 return peerexecutor(self) |
412 | 321 |
413 # Begin of ipeercommands interface. | 322 # Begin of ipeercommands interface. |
414 | |
415 def iterbatch(self): | |
416 return remoteiterbatcher(self) | |
417 | 323 |
418 @batchable | 324 @batchable |
419 def lookup(self, key): | 325 def lookup(self, key): |
420 self.requirecap('lookup', _('look up remote revision')) | 326 self.requirecap('lookup', _('look up remote revision')) |
421 f = future() | 327 f = future() |