##// 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 extensions,
120 extensions,
121 hg,
121 hg,
122 localrepo,
122 localrepo,
123 peer,
124 phases,
123 phases,
125 pushkey,
124 pushkey,
126 pycompat,
125 pycompat,
@@ -354,11 +353,11 b' def localrepolistkeys(orig, self, namesp'
354 else:
353 else:
355 return orig(self, namespace)
354 return orig(self, namespace)
356
355
357 @peer.batchable
356 @wireprotov1peer.batchable
358 def listkeyspatterns(self, namespace, patterns):
357 def listkeyspatterns(self, namespace, patterns):
359 if not self.capable('pushkey'):
358 if not self.capable('pushkey'):
360 yield {}, None
359 yield {}, None
361 f = peer.future()
360 f = wireprotov1peer.future()
362 self.ui.debug('preparing listkeys for "%s" with pattern "%s"\n' %
361 self.ui.debug('preparing listkeys for "%s" with pattern "%s"\n' %
363 (namespace, patterns))
362 (namespace, patterns))
364 yield {
363 yield {
@@ -49,7 +49,6 b' from . import ('
49 narrowspec,
49 narrowspec,
50 obsolete,
50 obsolete,
51 pathutil,
51 pathutil,
52 peer,
53 phases,
52 phases,
54 pushkey,
53 pushkey,
55 pycompat,
54 pycompat,
@@ -66,6 +65,7 b' from . import ('
66 txnutil,
65 txnutil,
67 util,
66 util,
68 vfs as vfsmod,
67 vfs as vfsmod,
68 wireprotov1peer,
69 )
69 )
70 from .utils import (
70 from .utils import (
71 procutil,
71 procutil,
@@ -153,6 +153,20 b" moderncaps = {'lookup', 'branchmap', 'pu"
153 'unbundle'}
153 'unbundle'}
154 legacycaps = moderncaps.union({'changegroupsubset'})
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 class localpeer(repository.peer):
170 class localpeer(repository.peer):
157 '''peer for a local repo; reflects only the most recent API'''
171 '''peer for a local repo; reflects only the most recent API'''
158
172
@@ -273,7 +287,7 b' class localpeer(repository.peer):'
273 # Begin of peer interface.
287 # Begin of peer interface.
274
288
275 def iterbatch(self):
289 def iterbatch(self):
276 return peer.localiterbatcher(self)
290 return localiterbatcher(self)
277
291
278 # End of peer interface.
292 # End of peer interface.
279
293
@@ -19,7 +19,6 b' from . import ('
19 changegroup as changegroupmod,
19 changegroup as changegroupmod,
20 encoding,
20 encoding,
21 error,
21 error,
22 peer,
23 pushkey as pushkeymod,
22 pushkey as pushkeymod,
24 pycompat,
23 pycompat,
25 repository,
24 repository,
@@ -29,7 +28,76 b' from . import ('
29
28
30 urlreq = util.urlreq
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 def __init__(self, remote):
101 def __init__(self, remote):
34 super(remoteiterbatcher, self).__init__()
102 super(remoteiterbatcher, self).__init__()
35 self._remote = remote
103 self._remote = remote
@@ -92,11 +160,6 b' class remoteiterbatcher(peer.iterbatcher'
92
160
93 yield finalfuture.value
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 def encodebatchcmds(req):
163 def encodebatchcmds(req):
101 """Return a ``cmds`` argument value for the ``batch`` command."""
164 """Return a ``cmds`` argument value for the ``batch`` command."""
102 escapearg = wireprototypes.escapebatcharg
165 escapearg = wireprototypes.escapebatcharg
@@ -9,9 +9,10 b' from __future__ import absolute_import, '
9
9
10 from mercurial import (
10 from mercurial import (
11 error,
11 error,
12 peer,
12 localrepo,
13 util,
13 util,
14 wireprotov1peer,
14 wireprotov1peer,
15
15 )
16 )
16
17
17 # equivalent of repo.repository
18 # equivalent of repo.repository
@@ -31,7 +32,7 b' class localthing(thing):'
31 return "Hello, %s" % name
32 return "Hello, %s" % name
32 def batchiter(self):
33 def batchiter(self):
33 '''Support for local batching.'''
34 '''Support for local batching.'''
34 return peer.localiterbatcher(self)
35 return localrepo.localiterbatcher(self)
35
36
36 # usage of "thing" interface
37 # usage of "thing" interface
37 def use(it):
38 def use(it):
@@ -51,7 +52,7 b' def use(it):'
51 bar2 = batch.bar(b="Uno", a="Due")
52 bar2 = batch.bar(b="Uno", a="Due")
52
53
53 # Future shouldn't be set until we submit().
54 # Future shouldn't be set until we submit().
54 assert isinstance(foo, peer.future)
55 assert isinstance(foo, wireprotov1peer.future)
55 assert not util.safehasattr(foo, 'value')
56 assert not util.safehasattr(foo, 'value')
56 assert not util.safehasattr(bar, 'value')
57 assert not util.safehasattr(bar, 'value')
57 batch.submit()
58 batch.submit()
@@ -179,16 +180,16 b' class remotething(thing):'
179 def batchiter(self):
180 def batchiter(self):
180 return wireprotov1peer.remoteiterbatcher(self)
181 return wireprotov1peer.remoteiterbatcher(self)
181
182
182 @peer.batchable
183 @wireprotov1peer.batchable
183 def foo(self, one, two=None):
184 def foo(self, one, two=None):
184 encargs = [('one', mangle(one),), ('two', mangle(two),)]
185 encargs = [('one', mangle(one),), ('two', mangle(two),)]
185 encresref = peer.future()
186 encresref = wireprotov1peer.future()
186 yield encargs, encresref
187 yield encargs, encresref
187 yield unmangle(encresref.value)
188 yield unmangle(encresref.value)
188
189
189 @peer.batchable
190 @wireprotov1peer.batchable
190 def bar(self, b, a):
191 def bar(self, b, a):
191 encresref = peer.future()
192 encresref = wireprotov1peer.future()
192 yield [('b', mangle(b),), ('a', mangle(a),)], encresref
193 yield [('b', mangle(b),), ('a', mangle(a),)], encresref
193 yield unmangle(encresref.value)
194 yield unmangle(encresref.value)
194
195
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now