aiortc: Seems datachannel.send() blocked by reading channel
while True
in rtcsctptransport.py blocks event loop if queue full on receive here
My suggestion is to rewrite it using asyncio.Queue
but it is not trivial
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 15 (5 by maintainers)
while True
has noawait
so asyncio loop blocked. No data can be sended at this moment.My english is not good. And i not fully anderstand your code. Need to go deeper)
^ FYI: I might actually pick this up at some point and implement it myself. Don’t rely on it though. 😺
Something like this:
If the user is interested in controlling the flow in its fullest form, it needs to use streams for messages. Otherwise, if it expects message size to not be an issue, it can also utilise bytes.
send
could also be split up intosend(message: Union[bytes, asyncio.StreamWriter])
andcreate_message() -> asyncio.StreamWriter
.The need to control the flow is only required for SCTP since DTLS/UDP has no flow control. I would propose to add a
drain
method. You can take the reader/writer classes of asyncio as inspiration.Edit 1: But please don’t treat a data channel as a stream because it isn’t. It’s a message stream of byte streams. If you create an API that resembles that, you can easily transfer a large file per message with proper flow control. 😃
Edit 2: Using asyncio, I would create the API in the following way: On the sender side, allow to create a
OutgoingMessage
instance which is a subclass ofasyncio.StreamWriter
. Once the stream is EOF, the message is complete. Only one instance is allowed to exist at the same time per channel (alternatively, use anasyncio.Queue
for enqueuing these instances). On the receiver side, raise an event (or better, use anasyncio.Queue
) to await newIncomingMessage
instances which are subclasses ofasyncio.StreamReader
. Read until EOF, then the message is complete. This API for example allows you to easily pipe a message’s content into an HTTP request usingaiohttp
while avoiding memory pressure.@nickaknudson that’s unrelated: as mentioned in the changelog send() is now a coroutine so you need to do:
await channel.send(“Foo”)