##// END OF EJS Templates
peer: scatter module to the wind (API)...
Gregory Szorc -
r37633:f3dc8239 default
parent child Browse files
Show More
@@ -120,7 +120,6 b' from mercurial import ('
120 120 extensions,
121 121 hg,
122 122 localrepo,
123 peer,
124 123 phases,
125 124 pushkey,
126 125 pycompat,
@@ -354,11 +353,11 b' def localrepolistkeys(orig, self, namesp'
354 353 else:
355 354 return orig(self, namespace)
356 355
357 @peer.batchable
356 @wireprotov1peer.batchable
358 357 def listkeyspatterns(self, namespace, patterns):
359 358 if not self.capable('pushkey'):
360 359 yield {}, None
361 f = peer.future()
360 f = wireprotov1peer.future()
362 361 self.ui.debug('preparing listkeys for "%s" with pattern "%s"\n' %
363 362 (namespace, patterns))
364 363 yield {
@@ -49,7 +49,6 b' from . import ('
49 49 narrowspec,
50 50 obsolete,
51 51 pathutil,
52 peer,
53 52 phases,
54 53 pushkey,
55 54 pycompat,
@@ -66,6 +65,7 b' from . import ('
66 65 txnutil,
67 66 util,
68 67 vfs as vfsmod,
68 wireprotov1peer,
69 69 )
70 70 from .utils import (
71 71 procutil,
@@ -153,6 +153,20 b" moderncaps = {'lookup', 'branchmap', 'pu"
153 153 'unbundle'}
154 154 legacycaps = moderncaps.union({'changegroupsubset'})
155 155
156 class localiterbatcher(wireprotov1peer.iterbatcher):
157 def __init__(self, local):
158 super(localiterbatcher, self).__init__()
159 self.local = local
160
161 def submit(self):
162 # submit for a local iter batcher is a noop
163 pass
164
165 def results(self):
166 for name, args, opts, resref in self.calls:
167 resref.set(getattr(self.local, name)(*args, **opts))
168 yield resref.value
169
156 170 class localpeer(repository.peer):
157 171 '''peer for a local repo; reflects only the most recent API'''
158 172
@@ -273,7 +287,7 b' class localpeer(repository.peer):'
273 287 # Begin of peer interface.
274 288
275 289 def iterbatch(self):
276 return peer.localiterbatcher(self)
290 return localiterbatcher(self)
277 291
278 292 # End of peer interface.
279 293
@@ -19,7 +19,6 b' from . import ('
19 19 changegroup as changegroupmod,
20 20 encoding,
21 21 error,
22 peer,
23 22 pushkey as pushkeymod,
24 23 pycompat,
25 24 repository,
@@ -29,7 +28,76 b' from . import ('
29 28
30 29 urlreq = util.urlreq
31 30
32 class remoteiterbatcher(peer.iterbatcher):
31 def batchable(f):
32 '''annotation for batchable methods
33
34 Such methods must implement a coroutine as follows:
35
36 @batchable
37 def sample(self, one, two=None):
38 # Build list of encoded arguments suitable for your wire protocol:
39 encargs = [('one', encode(one),), ('two', encode(two),)]
40 # Create future for injection of encoded result:
41 encresref = future()
42 # Return encoded arguments and future:
43 yield encargs, encresref
44 # Assuming the future to be filled with the result from the batched
45 # request now. Decode it:
46 yield decode(encresref.value)
47
48 The decorator returns a function which wraps this coroutine as a plain
49 method, but adds the original method as an attribute called "batchable",
50 which is used by remotebatch to split the call into separate encoding and
51 decoding phases.
52 '''
53 def plain(*args, **opts):
54 batchable = f(*args, **opts)
55 encargsorres, encresref = next(batchable)
56 if not encresref:
57 return encargsorres # a local result in this case
58 self = args[0]
59 cmd = pycompat.bytesurl(f.__name__) # ensure cmd is ascii bytestr
60 encresref.set(self._submitone(cmd, encargsorres))
61 return next(batchable)
62 setattr(plain, 'batchable', f)
63 return plain
64
65 class future(object):
66 '''placeholder for a value to be set later'''
67 def set(self, value):
68 if util.safehasattr(self, 'value'):
69 raise error.RepoError("future is already set")
70 self.value = value
71
72 class batcher(object):
73 '''base class for batches of commands submittable in a single request
74
75 All methods invoked on instances of this class are simply queued and
76 return a a future for the result. Once you call submit(), all the queued
77 calls are performed and the results set in their respective futures.
78 '''
79 def __init__(self):
80 self.calls = []
81 def __getattr__(self, name):
82 def call(*args, **opts):
83 resref = future()
84 # Please don't invent non-ascii method names, or you will
85 # give core hg a very sad time.
86 self.calls.append((name.encode('ascii'), args, opts, resref,))
87 return resref
88 return call
89 def submit(self):
90 raise NotImplementedError()
91
92 class iterbatcher(batcher):
93
94 def submit(self):
95 raise NotImplementedError()
96
97 def results(self):
98 raise NotImplementedError()
99
100 class remoteiterbatcher(iterbatcher):
33 101 def __init__(self, remote):
34 102 super(remoteiterbatcher, self).__init__()
35 103 self._remote = remote
@@ -92,11 +160,6 b' class remoteiterbatcher(peer.iterbatcher'
92 160
93 161 yield finalfuture.value
94 162
95 # Forward a couple of names from peer to make wireproto interactions
96 # slightly more sensible.
97 batchable = peer.batchable
98 future = peer.future
99
100 163 def encodebatchcmds(req):
101 164 """Return a ``cmds`` argument value for the ``batch`` command."""
102 165 escapearg = wireprototypes.escapebatcharg
@@ -9,9 +9,10 b' from __future__ import absolute_import, '
9 9
10 10 from mercurial import (
11 11 error,
12 peer,
12 localrepo,
13 13 util,
14 14 wireprotov1peer,
15
15 16 )
16 17
17 18 # equivalent of repo.repository
@@ -31,7 +32,7 b' class localthing(thing):'
31 32 return "Hello, %s" % name
32 33 def batchiter(self):
33 34 '''Support for local batching.'''
34 return peer.localiterbatcher(self)
35 return localrepo.localiterbatcher(self)
35 36
36 37 # usage of "thing" interface
37 38 def use(it):
@@ -51,7 +52,7 b' def use(it):'
51 52 bar2 = batch.bar(b="Uno", a="Due")
52 53
53 54 # Future shouldn't be set until we submit().
54 assert isinstance(foo, peer.future)
55 assert isinstance(foo, wireprotov1peer.future)
55 56 assert not util.safehasattr(foo, 'value')
56 57 assert not util.safehasattr(bar, 'value')
57 58 batch.submit()
@@ -179,16 +180,16 b' class remotething(thing):'
179 180 def batchiter(self):
180 181 return wireprotov1peer.remoteiterbatcher(self)
181 182
182 @peer.batchable
183 @wireprotov1peer.batchable
183 184 def foo(self, one, two=None):
184 185 encargs = [('one', mangle(one),), ('two', mangle(two),)]
185 encresref = peer.future()
186 encresref = wireprotov1peer.future()
186 187 yield encargs, encresref
187 188 yield unmangle(encresref.value)
188 189
189 @peer.batchable
190 @wireprotov1peer.batchable
190 191 def bar(self, b, a):
191 encresref = peer.future()
192 encresref = wireprotov1peer.future()
192 193 yield [('b', mangle(b),), ('a', mangle(a),)], encresref
193 194 yield unmangle(encresref.value)
194 195
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now