##// END OF EJS Templates
wireprotov1peer: simplify the way batchable rpcs are defined...
wireprotov1peer: simplify the way batchable rpcs are defined The scheme with futures/generator is confusing due to the way communication is done by side effects, especially with two different "future" objects. Just returning a request and a function to read the response is easier to understand. There are tests failures with the largefiles extension due to it aliasing one rpc to another one, which gets fixed in the next commit. Differential Revision: https://phab.mercurial-scm.org/D11211

File last commit:

r47209:05dd091d default
r48671:1364337a stable
Show More
test-batching.py
258 lines | 6.3 KiB | text/x-python | PythonLexer
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # test-batching.py - tests for transparent command batching
#
# Copyright 2011 Peter Arrenbrecht <peter@arrenbrecht.ch>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Robert Stanca
py3: use print_function in test-batching.py
r28732 from __future__ import absolute_import, print_function
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800
Gregory Szorc
wireproto: remove iterbatch() from peer interface (API)...
r37651 import contextlib
Yuya Nishihara
test-batching: stop direct symbol import of mercurial modules...
r28800 from mercurial import (
Gregory Szorc
peer: scatter module to the wind (API)...
r37633 localrepo,
Augie Fackler
py3: port test-batching.py to python3...
r41366 pycompat,
Gregory Szorc
wireproto: move version 1 peer functionality to standalone module (API)...
r37632 wireprotov1peer,
Augie Fackler
py3: port test-batching.py to python3...
r41366 )
Gregory Szorc
peer: scatter module to the wind (API)...
r37633
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
py3: port test-batching.py to python3...
r41366 def bprint(*bs):
print(*[pycompat.sysstr(b) for b in bs])
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # equivalent of repo.repository
class thing(object):
def hello(self):
Augie Fackler
py3: port test-batching.py to python3...
r41366 return b"Ready."
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # equivalent of localrepo.localrepository
class localthing(thing):
def foo(self, one, two=None):
if one:
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 return b"%s and %s" % (
one,
two,
)
Augie Fackler
py3: port test-batching.py to python3...
r41366 return b"Nope"
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def bar(self, b, a):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 return b"%s und %s" % (
b,
a,
)
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def greet(self, name=None):
Augie Fackler
py3: port test-batching.py to python3...
r41366 return b"Hello, %s" % name
Gregory Szorc
wireproto: remove iterbatch() from peer interface (API)...
r37651
@contextlib.contextmanager
def commandexecutor(self):
e = localrepo.localcommandexecutor(self)
try:
yield e
finally:
e.close()
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # usage of "thing" interface
def use(it):
# Direct call to base method shared between client and server.
Augie Fackler
py3: port test-batching.py to python3...
r41366 bprint(it.hello())
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
# Direct calls to proxied methods. They cause individual roundtrips.
Augie Fackler
py3: port test-batching.py to python3...
r41366 bprint(it.foo(b"Un", two=b"Deux"))
bprint(it.bar(b"Eins", b"Zwei"))
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 # Batched call to a couple of proxied methods.
Gregory Szorc
wireproto: remove iterbatch() from peer interface (API)...
r37651 with it.commandexecutor() as e:
Augie Fackler
py3: port test-batching.py to python3...
r41366 ffoo = e.callcommand(b'foo', {b'one': b'One', b'two': b'Two'})
fbar = e.callcommand(b'bar', {b'b': b'Eins', b'a': b'Zwei'})
fbar2 = e.callcommand(b'bar', {b'b': b'Uno', b'a': b'Due'})
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Augie Fackler
py3: port test-batching.py to python3...
r41366 bprint(ffoo.result())
bprint(fbar.result())
bprint(fbar2.result())
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # local usage
mylocal = localthing()
Robert Stanca
py3: use print_function in test-batching.py
r28732 print()
Augie Fackler
py3: port test-batching.py to python3...
r41366 bprint(b"== Local")
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 use(mylocal)
# demo remoting; mimicks what wireproto and HTTP/SSH do
# shared
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def escapearg(plain):
Augie Fackler
formatting: blacken the codebase...
r43346 return (
plain.replace(b':', b'::')
.replace(b',', b':,')
.replace(b';', b':;')
.replace(b'=', b':=')
)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def unescapearg(escaped):
Augie Fackler
formatting: blacken the codebase...
r43346 return (
escaped.replace(b':=', b'=')
.replace(b':;', b';')
.replace(b':,', b',')
.replace(b'::', b':')
)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
# server side
# equivalent of wireproto's global functions
Thomas Arendsen Hein
classes: fix class style problems found by b071cd58af50...
r14764 class server(object):
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def __init__(self, local):
self.local = local
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def _call(self, name, args):
Augie Fackler
py3: port test-batching.py to python3...
r41366 args = dict(arg.split(b'=', 1) for arg in args)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 return getattr(self, name)(**args)
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def perform(self, req):
Augie Fackler
py3: port test-batching.py to python3...
r41366 bprint(b"REQ:", req)
name, args = req.split(b'?', 1)
args = args.split(b'&')
vals = dict(arg.split(b'=', 1) for arg in args)
res = getattr(self, pycompat.sysstr(name))(**pycompat.strkwargs(vals))
bprint(b" ->", res)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 return res
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def batch(self, cmds):
res = []
Augie Fackler
py3: port test-batching.py to python3...
r41366 for pair in cmds.split(b';'):
name, args = pair.split(b':', 1)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 vals = {}
Augie Fackler
py3: port test-batching.py to python3...
r41366 for a in args.split(b','):
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 if a:
Augie Fackler
py3: port test-batching.py to python3...
r41366 n, v = a.split(b'=')
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 vals[n] = unescapearg(v)
Augie Fackler
formatting: blacken the codebase...
r43346 res.append(
escapearg(
getattr(self, pycompat.sysstr(name))(
**pycompat.strkwargs(vals)
)
)
)
Augie Fackler
py3: port test-batching.py to python3...
r41366 return b';'.join(res)
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def foo(self, one, two):
return mangle(self.local.foo(unmangle(one), unmangle(two)))
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def bar(self, b, a):
return mangle(self.local.bar(unmangle(b), unmangle(a)))
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def greet(self, name):
return mangle(self.local.greet(unmangle(name)))
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 myserver = server(mylocal)
# local side
# equivalent of wireproto.encode/decodelist, that is, type-specific marshalling
# here we just transform the strings a bit to check we're properly en-/decoding
def mangle(s):
Augie Fackler
py3: port test-batching.py to python3...
r41366 return b''.join(pycompat.bytechr(ord(c) + 1) for c in pycompat.bytestr(s))
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def unmangle(s):
Augie Fackler
py3: port test-batching.py to python3...
r41366 return b''.join(pycompat.bytechr(ord(c) - 1) for c in pycompat.bytestr(s))
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # equivalent of wireproto.wirerepository and something like http's wire format
class remotething(thing):
def __init__(self, server):
self.server = server
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def _submitone(self, name, args):
Augie Fackler
py3: port test-batching.py to python3...
r41366 req = name + b'?' + b'&'.join([b'%s=%s' % (n, v) for n, v in args])
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 return self.server.perform(req)
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def _submitbatch(self, cmds):
req = []
for name, args in cmds:
Augie Fackler
py3: port test-batching.py to python3...
r41366 args = b','.join(n + b'=' + escapearg(v) for n, v in args)
req.append(name + b':' + args)
req = b';'.join(req)
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 res = self._submitone(
b'batch',
[
(
b'cmds',
req,
)
],
)
Augie Fackler
py3: port test-batching.py to python3...
r41366 for r in res.split(b';'):
Gregory Szorc
wireproto: overhaul iterating batcher code (API)...
r33761 yield r
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Gregory Szorc
wireproto: remove iterbatch() from peer interface (API)...
r37651 @contextlib.contextmanager
def commandexecutor(self):
e = wireprotov1peer.peerexecutor(self)
try:
yield e
finally:
e.close()
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Gregory Szorc
peer: scatter module to the wind (API)...
r37633 @wireprotov1peer.batchable
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def foo(self, one, two=None):
Martin von Zweigbergk
wireprotopeer: clarify some variable names now that we allow snake_case...
r47209 encoded_args = [
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 (
b'one',
mangle(one),
),
(
b'two',
mangle(two),
),
]
Martin von Zweigbergk
wireprotopeer: clarify some variable names now that we allow snake_case...
r47209 encoded_res_future = wireprotov1peer.future()
yield encoded_args, encoded_res_future
yield unmangle(encoded_res_future.value)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Gregory Szorc
peer: scatter module to the wind (API)...
r37633 @wireprotov1peer.batchable
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 def bar(self, b, a):
Gregory Szorc
peer: scatter module to the wind (API)...
r37633 encresref = wireprotov1peer.future()
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 yield [
(
b'b',
mangle(b),
),
(
b'a',
mangle(a),
),
], encresref
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 yield unmangle(encresref.value)
# greet is coded directly. It therefore does not support batching. If it
# does appear in a batch, the batch is split around greet, and the call to
# greet is done in its own roundtrip.
def greet(self, name=None):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 return unmangle(
self._submitone(
b'greet',
[
(
b'name',
mangle(name),
)
],
)
)
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621
Augie Fackler
formatting: blacken the codebase...
r43346
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 # demo remote usage
myproxy = remotething(myserver)
Robert Stanca
py3: use print_function in test-batching.py
r28732 print()
Augie Fackler
py3: port test-batching.py to python3...
r41366 bprint(b"== Remote")
Peter Arrenbrecht
wireproto: add basic command batching infrastructure...
r14621 use(myproxy)