forked from goodboy/tractor
Call `MsgStream.aclose()` in `Context.open_stream.__aexit__()`
We weren't doing this originally I *think* just because of the path dependent nature of the way the code was developed (originally being mega pedantic about one-way vs. bidirectional streams) but, it doesn't seem like there's any issue just calling the stream's `.aclose()`; also have the benefit of just being less code and logic checks B)ipc_failure_while_streaming
parent
556f4626db
commit
aa4871b13d
|
@ -97,6 +97,9 @@ class ReceiveMsgStream(trio.abc.ReceiveChannel):
|
||||||
if self._eoc:
|
if self._eoc:
|
||||||
raise trio.EndOfChannel
|
raise trio.EndOfChannel
|
||||||
|
|
||||||
|
if self._closed:
|
||||||
|
raise trio.ClosedResourceError('This stream was closed')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
msg = await self._rx_chan.receive()
|
msg = await self._rx_chan.receive()
|
||||||
return msg['yield']
|
return msg['yield']
|
||||||
|
@ -110,6 +113,9 @@ class ReceiveMsgStream(trio.abc.ReceiveChannel):
|
||||||
# - 'error'
|
# - 'error'
|
||||||
# possibly just handle msg['stop'] here!
|
# possibly just handle msg['stop'] here!
|
||||||
|
|
||||||
|
if self._closed:
|
||||||
|
raise trio.ClosedResourceError('This stream was closed')
|
||||||
|
|
||||||
if msg.get('stop') or self._eoc:
|
if msg.get('stop') or self._eoc:
|
||||||
log.debug(f"{self} was stopped at remote end")
|
log.debug(f"{self} was stopped at remote end")
|
||||||
|
|
||||||
|
@ -189,7 +195,6 @@ class ReceiveMsgStream(trio.abc.ReceiveChannel):
|
||||||
return
|
return
|
||||||
|
|
||||||
self._eoc = True
|
self._eoc = True
|
||||||
self._closed = True
|
|
||||||
|
|
||||||
# NOTE: this is super subtle IPC messaging stuff:
|
# NOTE: this is super subtle IPC messaging stuff:
|
||||||
# Relay stop iteration to far end **iff** we're
|
# Relay stop iteration to far end **iff** we're
|
||||||
|
@ -206,29 +211,32 @@ class ReceiveMsgStream(trio.abc.ReceiveChannel):
|
||||||
|
|
||||||
# In the bidirectional case, `Context.open_stream()` will create
|
# In the bidirectional case, `Context.open_stream()` will create
|
||||||
# the `Actor._cids2qs` entry from a call to
|
# the `Actor._cids2qs` entry from a call to
|
||||||
# `Actor.get_context()` and will send the stop message in
|
# `Actor.get_context()` and will call us here to send the stop
|
||||||
# ``__aexit__()`` on teardown so it **does not** need to be
|
# msg in ``__aexit__()`` on teardown.
|
||||||
# called here.
|
try:
|
||||||
if not self._ctx._portal:
|
# NOTE: if this call is cancelled we expect this end to
|
||||||
# Only for 2 way streams can we can send stop from the
|
# handle as though the stop was never sent (though if it
|
||||||
# caller side.
|
# was it shouldn't matter since it's unlikely a user
|
||||||
try:
|
# will try to re-use a stream after attemping to close
|
||||||
# NOTE: if this call is cancelled we expect this end to
|
# it).
|
||||||
# handle as though the stop was never sent (though if it
|
with trio.CancelScope(shield=True):
|
||||||
# was it shouldn't matter since it's unlikely a user
|
await self._ctx.send_stop()
|
||||||
# will try to re-use a stream after attemping to close
|
|
||||||
# it).
|
|
||||||
with trio.CancelScope(shield=True):
|
|
||||||
await self._ctx.send_stop()
|
|
||||||
|
|
||||||
except (
|
except (
|
||||||
trio.BrokenResourceError,
|
trio.BrokenResourceError,
|
||||||
trio.ClosedResourceError
|
trio.ClosedResourceError
|
||||||
):
|
):
|
||||||
# the underlying channel may already have been pulled
|
# the underlying channel may already have been pulled
|
||||||
# in which case our stop message is meaningless since
|
# in which case our stop message is meaningless since
|
||||||
# it can't traverse the transport.
|
# it can't traverse the transport.
|
||||||
log.debug(f'Channel for {self} was already closed')
|
ctx = self._ctx
|
||||||
|
log.warning(
|
||||||
|
f'Stream was already destroyed?\n'
|
||||||
|
f'actor: {ctx.chan.uid}\n'
|
||||||
|
f'ctx id: {ctx.cid}'
|
||||||
|
)
|
||||||
|
|
||||||
|
self._closed = True
|
||||||
|
|
||||||
# Do we close the local mem chan ``self._rx_chan`` ??!?
|
# Do we close the local mem chan ``self._rx_chan`` ??!?
|
||||||
|
|
||||||
|
@ -594,30 +602,23 @@ class Context:
|
||||||
async with MsgStream(
|
async with MsgStream(
|
||||||
ctx=self,
|
ctx=self,
|
||||||
rx_chan=ctx._recv_chan,
|
rx_chan=ctx._recv_chan,
|
||||||
) as rchan:
|
) as stream:
|
||||||
|
|
||||||
if self._portal:
|
if self._portal:
|
||||||
self._portal._streams.add(rchan)
|
self._portal._streams.add(stream)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._stream_opened = True
|
self._stream_opened = True
|
||||||
|
|
||||||
# ensure we aren't cancelled before delivering
|
# XXX: do we need this?
|
||||||
# the stream
|
# ensure we aren't cancelled before yielding the stream
|
||||||
# await trio.lowlevel.checkpoint()
|
# await trio.lowlevel.checkpoint()
|
||||||
yield rchan
|
yield stream
|
||||||
|
|
||||||
# XXX: Make the stream "one-shot use". On exit, signal
|
# NOTE: Make the stream "one-shot use". On exit, signal
|
||||||
# ``trio.EndOfChannel``/``StopAsyncIteration`` to the
|
# ``trio.EndOfChannel``/``StopAsyncIteration`` to the
|
||||||
# far end.
|
# far end.
|
||||||
try:
|
await stream.aclose()
|
||||||
await self.send_stop()
|
|
||||||
except trio.BrokenResourceError:
|
|
||||||
log.warning(
|
|
||||||
f"Couldn't close: stream already broken?\n"
|
|
||||||
f'actor: {self.chan.uid}\n'
|
|
||||||
f'ctx id: {self.cid}'
|
|
||||||
)
|
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
if self._portal:
|
if self._portal:
|
||||||
|
|
Loading…
Reference in New Issue