wireproto: explicit API to create outgoing streams
It is better to create outgoing streams through the reactor so the
reactor knows about what streams are active and can track them
accordingly.
Test output changes slightly because frames from subsequent responses
no longer have the "stream begin" stream flag set because the stream
is now used across all responses.
Differential Revision: https://phab.mercurial-scm.org/D2947
--- a/mercurial/wireprotoframing.py Mon Mar 26 11:00:16 2018 -0700
+++ b/mercurial/wireprotoframing.py Mon Mar 26 13:59:56 2018 -0700
@@ -533,9 +533,11 @@
"""
self._deferoutput = deferoutput
self._state = 'idle'
+ self._nextoutgoingstreamid = 2
self._bufferedframegens = []
# stream id -> stream instance for all active streams from the client.
self._incomingstreams = {}
+ self._outgoingstreams = {}
# request id -> dict of commands that are actively being received.
self._receivingcommands = {}
# Request IDs that have been received and are actively being processed.
@@ -638,6 +640,16 @@
application=True),
}
+ def makeoutputstream(self):
+ """Create a stream to be used for sending data to the client."""
+ streamid = self._nextoutgoingstreamid
+ self._nextoutgoingstreamid += 2
+
+ s = stream(streamid)
+ self._outgoingstreams[streamid] = s
+
+ return s
+
def _makeerrorresult(self, msg):
return 'error', {
'message': msg,
--- a/mercurial/wireprotoserver.py Mon Mar 26 11:00:16 2018 -0700
+++ b/mercurial/wireprotoserver.py Mon Mar 26 13:59:56 2018 -0700
@@ -432,6 +432,8 @@
reactor = wireprotoframing.serverreactor(deferoutput=True)
seencommand = False
+ outstream = reactor.makeoutputstream()
+
while True:
frame = wireprotoframing.readframe(req.bodyfh)
if not frame:
@@ -444,8 +446,8 @@
continue
elif action == 'runcommand':
sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm,
- reqcommand, reactor, meta,
- issubsequent=seencommand)
+ reqcommand, reactor, outstream,
+ meta, issubsequent=seencommand)
if sentoutput:
return
@@ -476,7 +478,7 @@
% action)
def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor,
- command, issubsequent):
+ outstream, command, issubsequent):
"""Dispatch a wire protocol command made from HTTPv2 requests.
The authenticated permission (``authedperm``) along with the original
@@ -546,10 +548,9 @@
res.status = b'200 OK'
res.headers[b'Content-Type'] = FRAMINGTYPE
- stream = wireprotoframing.stream(2)
if isinstance(rsp, wireprototypes.bytesresponse):
- action, meta = reactor.onbytesresponseready(stream,
+ action, meta = reactor.onbytesresponseready(outstream,
command['requestid'],
rsp.data)
else:
--- a/tests/test-http-api-httpv2.t Mon Mar 26 11:00:16 2018 -0700
+++ b/tests/test-http-api-httpv2.t Mon Mar 26 13:59:56 2018 -0700
@@ -472,7 +472,7 @@
s> \x1d\x00\x00\x01\x00\x02\x01Bcustomreadonly bytes response
s> \r\n
s> 25\r\n
- s> \x1d\x00\x00\x03\x00\x02\x01Bcustomreadonly bytes response
+ s> \x1d\x00\x00\x03\x00\x02\x00Bcustomreadonly bytes response
s> \r\n
s> 0\r\n
s> \r\n
@@ -511,7 +511,7 @@
s> \x00\x00\x00\x03\x00\x02\x01B
s> \r\n
s> 26\r\n
- s> \x1e\x00\x00\x01\x00\x02\x01Bbookmarks \n
+ s> \x1e\x00\x00\x01\x00\x02\x00Bbookmarks \n
s> namespaces \n
s> phases
s> \r\n
--- a/tests/test-wireproto-serverreactor.py Mon Mar 26 11:00:16 2018 -0700
+++ b/tests/test-wireproto-serverreactor.py Mon Mar 26 13:59:56 2018 -0700
@@ -375,7 +375,7 @@
"""Multiple fully serviced commands with same request ID is allowed."""
reactor = makereactor()
results = []
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
results.append(self._sendsingleframe(
reactor, ffs(b'1 1 stream-begin command-name eos command')))
result = reactor.onbytesresponseready(outstream, 1, b'response1')
@@ -530,7 +530,7 @@
instream = framing.stream(1)
list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
result = reactor.onbytesresponseready(outstream, 1, b'response')
self.assertaction(result, 'sendframes')
self.assertframesequal(result[1]['framegen'], [
@@ -546,7 +546,7 @@
instream = framing.stream(1)
list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
result = reactor.onbytesresponseready(outstream, 1, first + second)
self.assertaction(result, 'sendframes')
self.assertframesequal(result[1]['framegen'], [
@@ -559,7 +559,7 @@
instream = framing.stream(1)
list(sendcommandframes(reactor, instream, 1, b'mycommand', {}))
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
result = reactor.onapplicationerror(outstream, 1, b'some message')
self.assertaction(result, 'sendframes')
self.assertframesequal(result[1]['framegen'], [
@@ -575,7 +575,7 @@
self.assertEqual(len(results), 1)
self.assertaction(results[0], 'runcommand')
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
result = reactor.onbytesresponseready(outstream, 1, b'response')
self.assertaction(result, 'noop')
result = reactor.oninputeof()
@@ -590,7 +590,7 @@
list(sendcommandframes(reactor, instream, 1, b'command1', {}))
list(sendcommandframes(reactor, instream, 3, b'command2', {}))
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
result = reactor.onbytesresponseready(outstream, 1, b'response1')
self.assertaction(result, 'noop')
result = reactor.onbytesresponseready(outstream, 3, b'response2')
@@ -610,7 +610,7 @@
list(sendcommandframes(reactor, instream, 5, b'command3', {}))
# Register results for commands out of order.
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
reactor.onbytesresponseready(outstream, 3, b'response3')
reactor.onbytesresponseready(outstream, 1, b'response1')
reactor.onbytesresponseready(outstream, 5, b'response5')
@@ -640,7 +640,7 @@
reactor = makereactor()
instream = framing.stream(1)
list(sendcommandframes(reactor, instream, 1, b'command1', {}))
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
reactor.onbytesresponseready(outstream, 1, b'response')
# We've registered the response but haven't sent it. From the
@@ -672,7 +672,7 @@
reactor = makereactor()
instream = framing.stream(1)
list(sendcommandframes(reactor, instream, 1, b'command1', {}))
- outstream = framing.stream(2)
+ outstream = reactor.makeoutputstream()
res = reactor.onbytesresponseready(outstream, 1, b'response')
list(res[1]['framegen'])