It’s really useful that asyncio can take a pre-fabricated sock under its management by accepting sock in create_connection. However, it then insists on keeping it until death do them part. I’m wondering if that is unavoidable.
I have a scenario where a socket has a slow, complicated ‘negotiation & set up’ phase, which is really convenient to manage using asyncio. After that startup, however, the socket transitions to a ‘datapath’ phase where lots of independent bidirectional message streams flow through it.
At that point it becomes beneficial for performance to use the inherent independence of a socket’s recv and send interfaces, by running separate reader and writer threads, to avoid one affecting latency on the other (yes, GIL and all, but most activity is non-python compute or IO in other worker threads). asyncio inherently precludes that since everything is bound to the event loop, which quite by definition is tied to a single thread.
At ver 3.10 this warning was added to the docs:
The sock argument transfers ownership of the socket to the transport created. To close the socket, call the transport’s
close()method
Which makes sense, but is it necessarily irreversible? Can the transport be kindly thanked for its services and requested to stop running the socket and shut down, just skipping close() on the socket?
I can think of adding an argument to close() or, perhaps better, create_connection(sock=..., sock_persists=True) making close() spare the socket.
I’m wondering what other people think of this.