Mercurial > public > mercurial-scm > hg
comparison mercurial/wireprotoframing.py @ 37722:89a16704114c
wireprotov2: define response data as CBOR
Previously, response data was defined as a stream of bytes. We had
the option to declare it as CBOR using a frame flag.
We've converged all wire protocol commands exposed on version 2 to
CBOR. I think consistency is important. The overhead to encoding
things with CBOR is minimal. Even a very large bytestring can be
efficiently encoded using an indefinite length bytestring. Now,
there are limitations with consumers not being able to efficiently
stream large CBOR values. But these feel like solvable problems.
This commit removes the "is CBOR" frame flag from command response
frames and defines the frame as always consisting of a stream of
CBOR values.
The framing protocol media type has been bumped to reflect this
BC change.
Differential Revision: https://phab.mercurial-scm.org/D3382
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 14 Apr 2018 12:07:31 -0700 |
parents | e6870bca1f47 |
children | e8fba6d578f0 |
comparison
equal
deleted
inserted
replaced
37721:f7673845b167 | 37722:89a16704114c |
---|---|
79 b'eos': FLAG_COMMAND_DATA_EOS, | 79 b'eos': FLAG_COMMAND_DATA_EOS, |
80 } | 80 } |
81 | 81 |
82 FLAG_BYTES_RESPONSE_CONTINUATION = 0x01 | 82 FLAG_BYTES_RESPONSE_CONTINUATION = 0x01 |
83 FLAG_BYTES_RESPONSE_EOS = 0x02 | 83 FLAG_BYTES_RESPONSE_EOS = 0x02 |
84 FLAG_BYTES_RESPONSE_CBOR = 0x04 | |
85 | 84 |
86 FLAGS_BYTES_RESPONSE = { | 85 FLAGS_BYTES_RESPONSE = { |
87 b'continuation': FLAG_BYTES_RESPONSE_CONTINUATION, | 86 b'continuation': FLAG_BYTES_RESPONSE_CONTINUATION, |
88 b'eos': FLAG_BYTES_RESPONSE_EOS, | 87 b'eos': FLAG_BYTES_RESPONSE_EOS, |
89 b'cbor': FLAG_BYTES_RESPONSE_CBOR, | |
90 } | 88 } |
91 | 89 |
92 FLAG_ERROR_RESPONSE_PROTOCOL = 0x01 | 90 FLAG_ERROR_RESPONSE_PROTOCOL = 0x01 |
93 FLAG_ERROR_RESPONSE_APPLICATION = 0x02 | 91 FLAG_ERROR_RESPONSE_APPLICATION = 0x02 |
94 | 92 |
348 payload=data) | 346 payload=data) |
349 | 347 |
350 if done: | 348 if done: |
351 break | 349 break |
352 | 350 |
353 def createbytesresponseframesfrombytes(stream, requestid, data, iscbor=False, | 351 def createbytesresponseframesfrombytes(stream, requestid, data, |
354 maxframesize=DEFAULT_MAX_FRAME_SIZE): | 352 maxframesize=DEFAULT_MAX_FRAME_SIZE): |
355 """Create a raw frame to send a bytes response from static bytes input. | 353 """Create a raw frame to send a bytes response from static bytes input. |
356 | 354 |
357 Returns a generator of bytearrays. | 355 Returns a generator of bytearrays. |
358 """ | 356 """ |
359 | 357 |
360 # Simple case of a single frame. | 358 # Simple case of a single frame. |
361 if len(data) <= maxframesize: | 359 if len(data) <= maxframesize: |
362 flags = FLAG_BYTES_RESPONSE_EOS | 360 flags = FLAG_BYTES_RESPONSE_EOS |
363 if iscbor: | |
364 flags |= FLAG_BYTES_RESPONSE_CBOR | |
365 | |
366 yield stream.makeframe(requestid=requestid, | 361 yield stream.makeframe(requestid=requestid, |
367 typeid=FRAME_TYPE_BYTES_RESPONSE, | 362 typeid=FRAME_TYPE_BYTES_RESPONSE, |
368 flags=flags, | 363 flags=flags, |
369 payload=data) | 364 payload=data) |
370 return | 365 return |
377 | 372 |
378 if done: | 373 if done: |
379 flags = FLAG_BYTES_RESPONSE_EOS | 374 flags = FLAG_BYTES_RESPONSE_EOS |
380 else: | 375 else: |
381 flags = FLAG_BYTES_RESPONSE_CONTINUATION | 376 flags = FLAG_BYTES_RESPONSE_CONTINUATION |
382 | |
383 if iscbor: | |
384 flags |= FLAG_BYTES_RESPONSE_CBOR | |
385 | 377 |
386 yield stream.makeframe(requestid=requestid, | 378 yield stream.makeframe(requestid=requestid, |
387 typeid=FRAME_TYPE_BYTES_RESPONSE, | 379 typeid=FRAME_TYPE_BYTES_RESPONSE, |
388 flags=flags, | 380 flags=flags, |
389 payload=chunk) | 381 payload=chunk) |
614 if not meth: | 606 if not meth: |
615 raise error.ProgrammingError('unhandled state: %s' % self._state) | 607 raise error.ProgrammingError('unhandled state: %s' % self._state) |
616 | 608 |
617 return meth(frame) | 609 return meth(frame) |
618 | 610 |
619 def onbytesresponseready(self, stream, requestid, data, iscbor=False): | 611 def onbytesresponseready(self, stream, requestid, data): |
620 """Signal that a bytes response is ready to be sent to the client. | 612 """Signal that a bytes response is ready to be sent to the client. |
621 | 613 |
622 The raw bytes response is passed as an argument. | 614 The raw bytes response is passed as an argument. |
623 """ | 615 """ |
624 ensureserverstream(stream) | 616 ensureserverstream(stream) |
625 | 617 |
626 def sendframes(): | 618 def sendframes(): |
627 for frame in createbytesresponseframesfrombytes(stream, requestid, | 619 for frame in createbytesresponseframesfrombytes(stream, requestid, |
628 data, | 620 data): |
629 iscbor=iscbor): | |
630 yield frame | 621 yield frame |
631 | 622 |
632 self._activecommands.remove(requestid) | 623 self._activecommands.remove(requestid) |
633 | 624 |
634 result = sendframes() | 625 result = sendframes() |
1065 | 1056 |
1066 return 'responsedata', { | 1057 return 'responsedata', { |
1067 'request': request, | 1058 'request': request, |
1068 'expectmore': frame.flags & FLAG_BYTES_RESPONSE_CONTINUATION, | 1059 'expectmore': frame.flags & FLAG_BYTES_RESPONSE_CONTINUATION, |
1069 'eos': frame.flags & FLAG_BYTES_RESPONSE_EOS, | 1060 'eos': frame.flags & FLAG_BYTES_RESPONSE_EOS, |
1070 'cbor': frame.flags & FLAG_BYTES_RESPONSE_CBOR, | |
1071 'data': frame.payload, | 1061 'data': frame.payload, |
1072 } | 1062 } |