Mercurial > public > mercurial-scm > hg
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. |