comparison mercurial/wireprotov2server.py @ 40172:30f70d11c224

wireprotov2: advertise recommended batch size for requests Currently, exchangev2 hardcodes the batch size for how many revisions to fetch per command request. A single value is not appropriate for every repository because some repositories may have a drastically different "shape" from other repositories. e.g. a repo with lots of small files may benefit from larger batch sizes than a repo with lots of large files. And depending on caching used by the server, the server may wish to control the number of commands (to e.g. mitigate overhead of following content redirects). This commit teaches wireprotov2 commands to declare extra metadata which is advertised as part of the command descriptor. The manifestdata command has been taught to advertise a recommended batch size for requests. Differential Revision: https://phab.mercurial-scm.org/D4975
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 08 Oct 2018 17:45:51 -0700
parents b5bf3dd6ec5b
children 6c42409691ec
comparison
equal deleted inserted replaced
40171:dac438b7346e 40172:30f70d11c224
516 caps['commands'][command] = { 516 caps['commands'][command] = {
517 'args': args, 517 'args': args,
518 'permissions': [entry.permission], 518 'permissions': [entry.permission],
519 } 519 }
520 520
521 if entry.extracapabilitiesfn:
522 extracaps = entry.extracapabilitiesfn(repo, proto)
523 caps['commands'][command].update(extracaps)
524
521 caps['rawrepoformats'] = sorted(repo.requirements & 525 caps['rawrepoformats'] = sorted(repo.requirements &
522 repo.supportedformats) 526 repo.supportedformats)
523 527
524 targets = getadvertisedredirecttargets(repo, proto) 528 targets = getadvertisedredirecttargets(repo, proto)
525 if targets: 529 if targets:
579 a redirect target. So targets should be advertised in the order the 583 a redirect target. So targets should be advertised in the order the
580 server prefers they be used. 584 server prefers they be used.
581 """ 585 """
582 return [] 586 return []
583 587
584 def wireprotocommand(name, args=None, permission='push', cachekeyfn=None): 588 def wireprotocommand(name, args=None, permission='push', cachekeyfn=None,
589 extracapabilitiesfn=None):
585 """Decorator to declare a wire protocol command. 590 """Decorator to declare a wire protocol command.
586 591
587 ``name`` is the name of the wire protocol command being provided. 592 ``name`` is the name of the wire protocol command being provided.
588 593
589 ``args`` is a dict defining arguments accepted by the command. Keys are 594 ``args`` is a dict defining arguments accepted by the command. Keys are
610 because otherwise commands not declaring their permissions could modify 615 because otherwise commands not declaring their permissions could modify
611 a repository that is supposed to be read-only. 616 a repository that is supposed to be read-only.
612 617
613 ``cachekeyfn`` defines an optional callable that can derive the 618 ``cachekeyfn`` defines an optional callable that can derive the
614 cache key for this request. 619 cache key for this request.
620
621 ``extracapabilitiesfn`` defines an optional callable that defines extra
622 command capabilities/parameters that are advertised next to the command
623 in the capabilities data structure describing the server. The callable
624 receives as arguments the repository and protocol objects. It returns
625 a dict of extra fields to add to the command descriptor.
615 626
616 Wire protocol commands are generators of objects to be serialized and 627 Wire protocol commands are generators of objects to be serialized and
617 sent to the client. 628 sent to the client.
618 629
619 If a command raises an uncaught exception, this will be translated into 630 If a command raises an uncaught exception, this will be translated into
673 raise error.ProgrammingError('%s command already registered ' 684 raise error.ProgrammingError('%s command already registered '
674 'for version 2' % name) 685 'for version 2' % name)
675 686
676 COMMANDS[name] = wireprototypes.commandentry( 687 COMMANDS[name] = wireprototypes.commandentry(
677 func, args=args, transports=transports, permission=permission, 688 func, args=args, transports=transports, permission=permission,
678 cachekeyfn=cachekeyfn) 689 cachekeyfn=cachekeyfn, extracapabilitiesfn=extracapabilitiesfn)
679 690
680 return func 691 return func
681 692
682 return register 693 return register
683 694
1089 # TODO handle exception. 1100 # TODO handle exception.
1090 node = repo.lookup(key) 1101 node = repo.lookup(key)
1091 1102
1092 yield node 1103 yield node
1093 1104
1105 def manifestdatacapabilities(repo, proto):
1106 batchsize = repo.ui.configint(
1107 b'experimental', b'server.manifestdata.recommended-batch-size')
1108
1109 return {
1110 b'recommendedbatchsize': batchsize,
1111 }
1112
1094 @wireprotocommand( 1113 @wireprotocommand(
1095 'manifestdata', 1114 'manifestdata',
1096 args={ 1115 args={
1097 'nodes': { 1116 'nodes': {
1098 'type': 'list', 1117 'type': 'list',
1113 'type': 'bytes', 1132 'type': 'bytes',
1114 'example': b'', 1133 'example': b'',
1115 }, 1134 },
1116 }, 1135 },
1117 permission='pull', 1136 permission='pull',
1118 cachekeyfn=makecommandcachekeyfn('manifestdata', 1, allargs=True)) 1137 cachekeyfn=makecommandcachekeyfn('manifestdata', 1, allargs=True),
1138 extracapabilitiesfn=manifestdatacapabilities)
1119 def manifestdata(repo, proto, haveparents, nodes, fields, tree): 1139 def manifestdata(repo, proto, haveparents, nodes, fields, tree):
1120 store = repo.manifestlog.getstorage(tree) 1140 store = repo.manifestlog.getstorage(tree)
1121 1141
1122 # Validate the node is known and abort on unknown revisions. 1142 # Validate the node is known and abort on unknown revisions.
1123 for node in nodes: 1143 for node in nodes: