tests/test-batching.py
changeset 33766 4c706037adef
parent 33765 e2fc2122029c
child 37614 a81d02ea65db
equal deleted inserted replaced
33765:e2fc2122029c 33766:4c706037adef
     6 # GNU General Public License version 2 or any later version.
     6 # GNU General Public License version 2 or any later version.
     7 
     7 
     8 from __future__ import absolute_import, print_function
     8 from __future__ import absolute_import, print_function
     9 
     9 
    10 from mercurial import (
    10 from mercurial import (
       
    11     error,
    11     peer,
    12     peer,
       
    13     util,
    12     wireproto,
    14     wireproto,
    13 )
    15 )
    14 
    16 
    15 # equivalent of repo.repository
    17 # equivalent of repo.repository
    16 class thing(object):
    18 class thing(object):
    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()