Support receiving fragmented messages without reassembly
Based on a suggestion by @cjerdonek in #296, I'm creating this new issue for clarity.
When receiving a fragmented message, it might be desireable to obtain the fragments without reassembling, to avoid a memory copy which may not be necessary.
Most likely this could be enabled by providing a variant of recv. I'd say it should be a separate function because it would have a different return type.
That function could return an async iterator (after we drop support for Python 3.4).
max_size should be re-interpreted as the maximum size of each chunk / frame rather than message.
The original suggestion was a file-like object. This needs some thought. It may require a layer of buffering which may negate the performance benefits.
When receiving a fragmented message, it might be desireable to obtain the fragments without reassembling, to avoid a memory copy which may not be necessary.
To show another use case: Forwarding of messages with flow-control and a backpressure signal on a chunk level.
Hello, are there any plans to go forward with this issue? It's great that we have a nice way to send fragmented messages, it'd be even greater to have it the other way round as well.
Perhaps the incoming queue should hold frames instead of messages. As you mentioned, each frame could be limited with max_size (for a frame now, not a message). read_message then could take frames from the queue instead of the socket. read_frame could become public API, it would get a frame from the queue. The queue should probably only hold data frames and control frames could be processed in the transfer_data task (or one of its callees probably). I may miss something, but it seems to be doable.
P.S. Merry Christmas!
@dmitryduka Your proposal doesn't work because read_frame is executed by transfer_data_task; you can't call it separately.
If the ability to receive individual fragments instead of messages must be provided on a per-message basis, there are several situations to consider:
- nothing received
- one message partially received
- at least one message fully received
I'm afraid the logic around _pop_message_waiter could get more complicated if it needs to handle all these situations.
Also, this will require switching from a message queue to a frame queue, which will open backwards compatibility questions.
To handle streaming data would it be possible to do this on the message queue with out the finbit being set?
Yes, that's what this issue is about — "fragmented messages" don't have the FIN bit set, except on the last frame.
The new threading-based API supports this.
The new threading-based API supports this.
Any plans of it to the asyncio-based API and/or the Sans API's?
The plan for asyncio is #1332, ETA 1 to 3 years from now.
It is de facto possible in the Sans-I/O API because that layer only knows about frames. It doesn't reassemble fragmented messages.