Show More
@@ -35,7 +35,7 b' from .utils import hashutil' | |||
|
35 | 35 | urlreq = util.urlreq |
|
36 | 36 | |
|
37 | 37 | |
|
38 | def batchable(f): | |
|
38 | def batchable_new_style(f): | |
|
39 | 39 | """annotation for batchable methods |
|
40 | 40 | |
|
41 | 41 | Such methods must implement a coroutine as follows: |
@@ -44,13 +44,9 b' def batchable(f):' | |||
|
44 | 44 | def sample(self, one, two=None): |
|
45 | 45 | # Build list of encoded arguments suitable for your wire protocol: |
|
46 | 46 | encoded_args = [('one', encode(one),), ('two', encode(two),)] |
|
47 | # Create future for injection of encoded result: | |
|
48 | encoded_res_future = future() | |
|
49 |
|
|
|
50 | yield encoded_args, encoded_res_future | |
|
51 | # Assuming the future to be filled with the result from the batched | |
|
52 | # request now. Decode it: | |
|
53 | yield decode(encoded_res_future.value) | |
|
47 | # Return it, along with a function that will receive the result | |
|
48 | # from the batched request. | |
|
49 | return encoded_args, decode | |
|
54 | 50 | |
|
55 | 51 | The decorator returns a function which wraps this coroutine as a plain |
|
56 | 52 | method, but adds the original method as an attribute called "batchable", |
@@ -59,20 +55,37 b' def batchable(f):' | |||
|
59 | 55 | """ |
|
60 | 56 | |
|
61 | 57 | def plain(*args, **opts): |
|
62 |
|
|
|
63 | encoded_args_or_res, encoded_res_future = next(batchable) | |
|
64 | if not encoded_res_future: | |
|
58 | encoded_args_or_res, decode = f(*args, **opts) | |
|
59 | if not decode: | |
|
65 | 60 | return encoded_args_or_res # a local result in this case |
|
66 | 61 | self = args[0] |
|
67 | 62 | cmd = pycompat.bytesurl(f.__name__) # ensure cmd is ascii bytestr |
|
68 |
encoded_res |
|
|
69 | return next(batchable) | |
|
63 | encoded_res = self._submitone(cmd, encoded_args_or_res) | |
|
64 | return decode(encoded_res) | |
|
70 | 65 | |
|
71 | 66 | setattr(plain, 'batchable', f) |
|
72 | 67 | setattr(plain, '__name__', f.__name__) |
|
73 | 68 | return plain |
|
74 | 69 | |
|
75 | 70 | |
|
71 | def batchable(f): | |
|
72 | def upgraded(*args, **opts): | |
|
73 | batchable = f(*args, **opts) | |
|
74 | encoded_args_or_res, encoded_res_future = next(batchable) | |
|
75 | if not encoded_res_future: | |
|
76 | decode = None | |
|
77 | else: | |
|
78 | ||
|
79 | def decode(d): | |
|
80 | encoded_res_future.set(d) | |
|
81 | return next(batchable) | |
|
82 | ||
|
83 | return encoded_args_or_res, decode | |
|
84 | ||
|
85 | setattr(upgraded, '__name__', f.__name__) | |
|
86 | return batchable_new_style(upgraded) | |
|
87 | ||
|
88 | ||
|
76 | 89 | class future(object): |
|
77 | 90 | '''placeholder for a value to be set later''' |
|
78 | 91 | |
@@ -248,25 +261,18 b' class peerexecutor(object):' | |||
|
248 | 261 | continue |
|
249 | 262 | |
|
250 | 263 | try: |
|
251 |
|
|
|
264 | encoded_args_or_res, decode = fn.batchable( | |
|
252 | 265 | fn.__self__, **pycompat.strkwargs(args) |
|
253 | 266 | ) |
|
254 | 267 | except Exception: |
|
255 | 268 | pycompat.future_set_exception_info(f, sys.exc_info()[1:]) |
|
256 | 269 | return |
|
257 | 270 | |
|
258 | # Encoded arguments and future holding remote result. | |
|
259 | try: | |
|
260 | encoded_args_or_res, fremote = next(batchable) | |
|
261 | except Exception: | |
|
262 | pycompat.future_set_exception_info(f, sys.exc_info()[1:]) | |
|
263 | return | |
|
264 | ||
|
265 | if not fremote: | |
|
271 | if not decode: | |
|
266 | 272 | f.set_result(encoded_args_or_res) |
|
267 | 273 | else: |
|
268 | 274 | requests.append((command, encoded_args_or_res)) |
|
269 |
states.append((command, f, batchable, |
|
|
275 | states.append((command, f, batchable, decode)) | |
|
270 | 276 | |
|
271 | 277 | if not requests: |
|
272 | 278 | return |
@@ -319,7 +325,7 b' class peerexecutor(object):' | |||
|
319 | 325 | def _readbatchresponse(self, states, wireresults): |
|
320 | 326 | # Executes in a thread to read data off the wire. |
|
321 | 327 | |
|
322 |
for command, f, batchable, |
|
|
328 | for command, f, batchable, decode in states: | |
|
323 | 329 | # Grab raw result off the wire and teach the internal future |
|
324 | 330 | # about it. |
|
325 | 331 | try: |
@@ -334,11 +340,8 b' class peerexecutor(object):' | |||
|
334 | 340 | ) |
|
335 | 341 | ) |
|
336 | 342 | else: |
|
337 | fremote.set(remoteresult) | |
|
338 | ||
|
339 | # And ask the coroutine to decode that value. | |
|
340 | 343 | try: |
|
341 |
result = |
|
|
344 | result = decode(remoteresult) | |
|
342 | 345 | except Exception: |
|
343 | 346 | pycompat.future_set_exception_info(f, sys.exc_info()[1:]) |
|
344 | 347 | else: |
General Comments 0
You need to be logged in to leave comments.
Login now