Mercurial > hg
annotate mercurial/wireprotov2peer.py @ 37725:3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
The error handling mechanism for the new wire protocol isn't very
well-defined. This commit takes us a step in the right direction
by introducing a leading CBOR map for command responses. This map
will contain an overall result of the command.
Currently, the map indicates whether the command was overall
successful or if an error occurred. And if an error occurred, that
error is present in the map.
There is still a dedicated error frame. My intent is to use that
for protocol-level errors and for errors that are encountered after
the initial response frame has been sent. This will be clarified in a
later commit.
Differential Revision: https://phab.mercurial-scm.org/D3385
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 14 Apr 2018 15:19:36 -0700 |
parents | 89a16704114c |
children | 1467b6c27ff9 |
rev | line source |
---|---|
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
1 # wireprotov2peer.py - client side code for wire protocol version 2 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
2 # |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com> |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
4 # |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
6 # GNU General Public License version 2 or any later version. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
7 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
8 from __future__ import absolute_import |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
9 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
10 from .i18n import _ |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
11 from .thirdparty import ( |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
12 cbor, |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
13 ) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
14 from . import ( |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
15 encoding, |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
16 error, |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
17 util, |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
18 wireprotoframing, |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
19 ) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
20 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
21 def formatrichmessage(atoms): |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
22 """Format an encoded message from the framing protocol.""" |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
23 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
24 chunks = [] |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
25 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
26 for atom in atoms: |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
27 msg = _(atom[b'msg']) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
28 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
29 if b'args' in atom: |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
30 msg = msg % atom[b'args'] |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
31 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
32 chunks.append(msg) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
33 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
34 return b''.join(chunks) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
35 |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
36 class commandresponse(object): |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
37 """Represents the response to a command request.""" |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
38 |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
39 def __init__(self, requestid, command): |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
40 self.requestid = requestid |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
41 self.command = command |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
42 |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
43 self.b = util.bytesio() |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
44 |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
45 def cborobjects(self): |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
46 """Obtain decoded CBOR objects from this response.""" |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
47 size = self.b.tell() |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
48 self.b.seek(0) |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
49 |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
50 decoder = cbor.CBORDecoder(self.b) |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
51 |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
52 while self.b.tell() < size: |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
53 yield decoder.decode() |
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
54 |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
55 class clienthandler(object): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
56 """Object to handle higher-level client activities. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
57 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
58 The ``clientreactor`` is used to hold low-level state about the frame-based |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
59 protocol, such as which requests and streams are active. This type is used |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
60 for higher-level operations, such as reading frames from a socket, exposing |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
61 and managing a higher-level primitive for representing command responses, |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
62 etc. This class is what peers should probably use to bridge wire activity |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
63 with the higher-level peer API. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
64 """ |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
65 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
66 def __init__(self, ui, clientreactor): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
67 self._ui = ui |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
68 self._reactor = clientreactor |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
69 self._requests = {} |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
70 self._futures = {} |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
71 self._responses = {} |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
72 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
73 def callcommand(self, command, args, f): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
74 """Register a request to call a command. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
75 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
76 Returns an iterable of frames that should be sent over the wire. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
77 """ |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
78 request, action, meta = self._reactor.callcommand(command, args) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
79 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
80 if action != 'noop': |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
81 raise error.ProgrammingError('%s not yet supported' % action) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
82 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
83 rid = request.requestid |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
84 self._requests[rid] = request |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
85 self._futures[rid] = f |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
86 self._responses[rid] = commandresponse(rid, command) |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
87 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
88 return iter(()) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
89 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
90 def flushcommands(self): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
91 """Flush all queued commands. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
92 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
93 Returns an iterable of frames that should be sent over the wire. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
94 """ |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
95 action, meta = self._reactor.flushcommands() |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
96 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
97 if action != 'sendframes': |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
98 raise error.ProgrammingError('%s not yet supported' % action) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
99 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
100 return meta['framegen'] |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
101 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
102 def readframe(self, fh): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
103 """Attempt to read and process a frame. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
104 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
105 Returns None if no frame was read. Presumably this means EOF. |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
106 """ |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
107 frame = wireprotoframing.readframe(fh) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
108 if frame is None: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
109 # TODO tell reactor? |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
110 return |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
111 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
112 self._ui.note(_('received %r\n') % frame) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
113 self._processframe(frame) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
114 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
115 return True |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
116 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
117 def _processframe(self, frame): |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
118 """Process a single read frame.""" |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
119 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
120 action, meta = self._reactor.onframerecv(frame) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
121 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
122 if action == 'error': |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
123 e = error.RepoError(meta['message']) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
124 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
125 if frame.requestid in self._futures: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
126 self._futures[frame.requestid].set_exception(e) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
127 else: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
128 raise e |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
129 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
130 if frame.requestid not in self._requests: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
131 raise error.ProgrammingError( |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
132 'received frame for unknown request; this is either a bug in ' |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
133 'the clientreactor not screening for this or this instance was ' |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
134 'never told about this request: %r' % frame) |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
135 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
136 response = self._responses[frame.requestid] |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
137 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
138 if action == 'responsedata': |
37720
d715a85003c8
wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37719
diff
changeset
|
139 response.b.write(meta['data']) |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
140 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
141 if meta['eos']: |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
142 # If the command has a decoder, resolve the future to the |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
143 # decoded value. Otherwise resolve to the rich response object. |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
144 decoder = COMMAND_DECODERS.get(response.command) |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
145 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
146 # TODO consider always resolving the overall status map. |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
147 if decoder: |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
148 objs = response.cborobjects() |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
149 |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
150 overall = next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
151 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
152 if overall['status'] == 'ok': |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
153 self._futures[frame.requestid].set_result(decoder(objs)) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
154 else: |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
155 e = error.RepoError( |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
156 formatrichmessage(overall['error']['message'])) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
157 self._futures[frame.requestid].set_exception(e) |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
158 else: |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
159 self._futures[frame.requestid].set_result(response) |
37719
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
160 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
161 del self._requests[frame.requestid] |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
162 del self._futures[frame.requestid] |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
163 |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
164 else: |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
165 raise error.ProgrammingError( |
a656cba08a04
wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
166 'unhandled action from clientreactor: %s' % action) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
167 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
168 def decodebranchmap(objs): |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
169 # Response should be a single CBOR map of branch name to array of nodes. |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
170 bm = next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
171 |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
172 return {encoding.tolocal(k): v for k, v in bm.items()} |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
173 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
174 def decodeheads(objs): |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
175 # Array of node bytestrings. |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
176 return next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
177 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
178 def decodeknown(objs): |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
179 # Bytestring where each byte is a 0 or 1. |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
180 raw = next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
181 |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
182 return [True if c == '1' else False for c in raw] |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
183 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
184 def decodelistkeys(objs): |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
185 # Map with bytestring keys and values. |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
186 return next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
187 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
188 def decodelookup(objs): |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
189 return next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
190 |
37725
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
191 def decodepushkey(objs): |
3ea8323d6f95
wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37722
diff
changeset
|
192 return next(objs) |
37721
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
193 |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
194 COMMAND_DECODERS = { |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
195 'branchmap': decodebranchmap, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
196 'heads': decodeheads, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
197 'known': decodeknown, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
198 'listkeys': decodelistkeys, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
199 'lookup': decodelookup, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
200 'pushkey': decodepushkey, |
f7673845b167
wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents:
37720
diff
changeset
|
201 } |