-
-
Notifications
You must be signed in to change notification settings - Fork 32
Description
This means:
- Rename the
closemethod toaclose - Inherit from
AsyncResource, soisinstancechecks work and you get__aenter__and__aexit__methods for free - Make sure that if
acloseis cancelled, then it closes the underlying connection and cleans everything up, without blocking
The last one is a bit tricky... you need to think about the case where both the call to aclose and the writer task are cancelled together, or the case where just the aclose call is cancelled, and in both cases shut down the reader and writer tasks as well as closing the underlying socket.
It might be simpler to get rid of the writer task entirely? Instead, you could call send_all from inside the task that's trying to send something. Like, here's a simplified sketch of what I'm imagining:
def _flush_sends(self):
async with self._send_lock:
data = self._wsproto.bytes_to_send()
if data:
await self._stream.send_all(data)
async def send_message(self, message):
self._wsproto.send_data(message)
await self._flush_sends()
async def aclose(self, code=1000, reason=None):
try:
self._wsproto.close(code=code, reason=reason)
await self._flush_sends()
finally:
# We do this even if _flush_sends was cancelled
await self._stream.aclose()I guess this will also kill the reader indirectly, by causing its current-or-next call to receive_some to raise ClosedResourceError. We might want to catch that and handle it somehow.
It would also be good if closing the websocket caused any waiting calls to get_message to raise an error. That will be easier once python-trio/trio#586 lands and we can close the message queue.