comparison mercurial/localrepo.py @ 37630:e1b32dc4646c

wireproto: implement command executor interface for version 1 peers Now that we've defined our new interface for issuing commands, let's implement it. We add the interface to the base peer interface. This means all peer types must implement it. The only peer types that we have are the local peer in localrepo and a shared wire peer for version 1 of the wire protocol. The local peer implementation is pretty straightforward. We don't do anything fancy and just return a resolved future with the result of a method call. This is similar to what localiterbatcher does. The wire protocol version 1 implementation is a bit more complicated and is a more robust implementation. The wire executor queues commands by default. And because the new executor interface always allows multiple commands but not all version 1 commands are @batchable, it has to check that the requested commands are batchable if multiple commands are being requested. The wire executor currently only supports executing a single command. This is for simplicity reasons. Support for multiple commands will be added in a separate commit. To prove the new interface works, a call to the "known" command during discovery has been updated to use the new API. It's worth noting that both implementations require a method having the command name to exist on the peer. There is at least one caller in core that don't have a method calls peer._call() directly. We may need to shore up the requirements later... Differential Revision: https://phab.mercurial-scm.org/D3268
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 13 Apr 2018 10:51:23 -0700
parents f3dc8239e3a9
children 33a6eee08db2
comparison
equal deleted inserted replaced
37629:fa0382088993 37630:e1b32dc4646c
9 9
10 import errno 10 import errno
11 import hashlib 11 import hashlib
12 import os 12 import os
13 import random 13 import random
14 import sys
14 import time 15 import time
15 import weakref 16 import weakref
16 17
17 from .i18n import _ 18 from .i18n import _
18 from .node import ( 19 from .node import (
165 def results(self): 166 def results(self):
166 for name, args, opts, resref in self.calls: 167 for name, args, opts, resref in self.calls:
167 resref.set(getattr(self.local, name)(*args, **opts)) 168 resref.set(getattr(self.local, name)(*args, **opts))
168 yield resref.value 169 yield resref.value
169 170
171 @zi.implementer(repository.ipeercommandexecutor)
172 class localcommandexecutor(object):
173 def __init__(self, peer):
174 self._peer = peer
175 self._sent = False
176 self._closed = False
177
178 def __enter__(self):
179 return self
180
181 def __exit__(self, exctype, excvalue, exctb):
182 self.close()
183
184 def callcommand(self, command, args):
185 if self._sent:
186 raise error.ProgrammingError('callcommand() cannot be used after '
187 'sendcommands()')
188
189 if self._closed:
190 raise error.ProgrammingError('callcommand() cannot be used after '
191 'close()')
192
193 # We don't need to support anything fancy. Just call the named
194 # method on the peer and return a resolved future.
195 fn = getattr(self._peer, pycompat.sysstr(command))
196
197 f = pycompat.futures.Future()
198
199 try:
200 result = fn(**args)
201 except Exception:
202 f.set_exception_info(*sys.exc_info()[1:])
203 else:
204 f.set_result(result)
205
206 return f
207
208 def sendcommands(self):
209 self._sent = True
210
211 def close(self):
212 self._closed = True
213
170 class localpeer(repository.peer): 214 class localpeer(repository.peer):
171 '''peer for a local repo; reflects only the most recent API''' 215 '''peer for a local repo; reflects only the most recent API'''
172 216
173 def __init__(self, repo, caps=None): 217 def __init__(self, repo, caps=None):
174 super(localpeer, self).__init__() 218 super(localpeer, self).__init__()
283 stringutil.forcebytestr(exc)) 327 stringutil.forcebytestr(exc))
284 328
285 # End of _basewirecommands interface. 329 # End of _basewirecommands interface.
286 330
287 # Begin of peer interface. 331 # Begin of peer interface.
332
333 def commandexecutor(self):
334 return localcommandexecutor(self)
288 335
289 def iterbatch(self): 336 def iterbatch(self):
290 return localiterbatcher(self) 337 return localiterbatcher(self)
291 338
292 # End of peer interface. 339 # End of peer interface.