25 return "Nope" |
27 return "Nope" |
26 def bar(self, b, a): |
28 def bar(self, b, a): |
27 return "%s und %s" % (b, a,) |
29 return "%s und %s" % (b, a,) |
28 def greet(self, name=None): |
30 def greet(self, name=None): |
29 return "Hello, %s" % name |
31 return "Hello, %s" % name |
30 def batch(self): |
32 def batchiter(self): |
31 '''Support for local batching.''' |
33 '''Support for local batching.''' |
32 return peer.localbatch(self) |
34 return peer.localiterbatcher(self) |
33 |
35 |
34 # usage of "thing" interface |
36 # usage of "thing" interface |
35 def use(it): |
37 def use(it): |
36 |
38 |
37 # Direct call to base method shared between client and server. |
39 # Direct call to base method shared between client and server. |
39 |
41 |
40 # Direct calls to proxied methods. They cause individual roundtrips. |
42 # Direct calls to proxied methods. They cause individual roundtrips. |
41 print(it.foo("Un", two="Deux")) |
43 print(it.foo("Un", two="Deux")) |
42 print(it.bar("Eins", "Zwei")) |
44 print(it.bar("Eins", "Zwei")) |
43 |
45 |
44 # Batched call to a couple of (possibly proxied) methods. |
46 # Batched call to a couple of proxied methods. |
45 batch = it.batch() |
47 batch = it.batchiter() |
46 # The calls return futures to eventually hold results. |
48 # The calls return futures to eventually hold results. |
47 foo = batch.foo(one="One", two="Two") |
49 foo = batch.foo(one="One", two="Two") |
48 bar = batch.bar("Eins", "Zwei") |
50 bar = batch.bar("Eins", "Zwei") |
49 # We can call non-batchable proxy methods, but the break the current batch |
|
50 # request and cause additional roundtrips. |
|
51 greet = batch.greet(name="John Smith") |
|
52 # We can also add local methods into the mix, but they break the batch too. |
|
53 hello = batch.hello() |
|
54 bar2 = batch.bar(b="Uno", a="Due") |
51 bar2 = batch.bar(b="Uno", a="Due") |
55 # Only now are all the calls executed in sequence, with as few roundtrips |
52 |
56 # as possible. |
53 # Future shouldn't be set until we submit(). |
|
54 assert isinstance(foo, peer.future) |
|
55 assert not util.safehasattr(foo, 'value') |
|
56 assert not util.safehasattr(bar, 'value') |
57 batch.submit() |
57 batch.submit() |
58 # After the call to submit, the futures actually contain values. |
58 # Call results() to obtain results as a generator. |
|
59 results = batch.results() |
|
60 |
|
61 # Future results shouldn't be set until we consume a value. |
|
62 assert not util.safehasattr(foo, 'value') |
|
63 foovalue = next(results) |
|
64 assert util.safehasattr(foo, 'value') |
|
65 assert foovalue == foo.value |
59 print(foo.value) |
66 print(foo.value) |
|
67 next(results) |
60 print(bar.value) |
68 print(bar.value) |
61 print(greet.value) |
69 next(results) |
62 print(hello.value) |
|
63 print(bar2.value) |
70 print(bar2.value) |
|
71 |
|
72 # We should be at the end of the results generator. |
|
73 try: |
|
74 next(results) |
|
75 except StopIteration: |
|
76 print('proper end of results generator') |
|
77 else: |
|
78 print('extra emitted element!') |
|
79 |
|
80 # Attempting to call a non-batchable method inside a batch fails. |
|
81 batch = it.batchiter() |
|
82 try: |
|
83 batch.greet(name='John Smith') |
|
84 except error.ProgrammingError as e: |
|
85 print(e) |
|
86 |
|
87 # Attempting to call a local method inside a batch fails. |
|
88 batch = it.batchiter() |
|
89 try: |
|
90 batch.hello() |
|
91 except error.ProgrammingError as e: |
|
92 print(e) |
64 |
93 |
65 # local usage |
94 # local usage |
66 mylocal = localthing() |
95 mylocal = localthing() |
67 print() |
96 print() |
68 print("== Local") |
97 print("== Local") |
142 for name, args in cmds: |
171 for name, args in cmds: |
143 args = ','.join(n + '=' + escapearg(v) for n, v in args) |
172 args = ','.join(n + '=' + escapearg(v) for n, v in args) |
144 req.append(name + ':' + args) |
173 req.append(name + ':' + args) |
145 req = ';'.join(req) |
174 req = ';'.join(req) |
146 res = self._submitone('batch', [('cmds', req,)]) |
175 res = self._submitone('batch', [('cmds', req,)]) |
147 return res.split(';') |
176 for r in res.split(';'): |
148 |
177 yield r |
149 def batch(self): |
178 |
150 return wireproto.remotebatch(self) |
179 def batchiter(self): |
|
180 return wireproto.remoteiterbatcher(self) |
151 |
181 |
152 @peer.batchable |
182 @peer.batchable |
153 def foo(self, one, two=None): |
183 def foo(self, one, two=None): |
154 encargs = [('one', mangle(one),), ('two', mangle(two),)] |
184 encargs = [('one', mangle(one),), ('two', mangle(two),)] |
155 encresref = peer.future() |
185 encresref = peer.future() |