Clarify pointer and IPC cancellation contracts

Source prose left the stalled transport peer ambiguous, omitted why a
local namespace pointer retains its object and described cancellation
as interrupting a frame write which is now shielded.

Identify remote-peer and bounded-cancel behavior, document process-local
pointer caching, and explain the shield completion checkpoint which
makes startup cancellation protocol-safe on a connected channel.

Review: PR #481 (goodboy)
https://github.com/goodboy/tractor/pull/481#pullrequestreview-5012942328

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
wkt/to_actor_subpkg
Gud Boi 2026-08-25 01:38:17 -04:00
parent 773370a423
commit bf46f5cc5e
3 changed files with 22 additions and 9 deletions

View File

@ -518,9 +518,10 @@ class MsgpackTransport(MsgTransport):
# the frame is complete, the explicit checkpoint # the frame is complete, the explicit checkpoint
# immediately delivers any pending cancellation. # immediately delivers any pending cancellation.
# #
# Ordinary sends may delay cancellation while a peer is # Ordinary sends may delay cancellation while the remote
# not reading. Actor-wide cancel requests pass their own # peer actor is not reading. Bounded actor/context cancel
# deadline so this operation can close a stalled stream. # requests pass an absolute deadline so this operation
# can close a stalled stream.
with trio.CancelScope( with trio.CancelScope(
deadline=send_deadline, deadline=send_deadline,
shield=True, shield=True,

View File

@ -123,6 +123,15 @@ class NamespacePath(str):
ref: type|object, ref: type|object,
) -> NamespacePath: ) -> NamespacePath:
'''
Build a path while retaining its process-local object reference.
The originating process already holds `ref`; caching it prevents
`to_tuple()` from immediately importing and resolving the same
object again. Serialized paths carry only the `str` value and
therefore resolve lazily through `load_ref()` after decoding.
'''
fqnp: tuple[str, str] = cls._mk_fqnp(ref) fqnp: tuple[str, str] = cls._mk_fqnp(ref)
nsp = cls(':'.join(fqnp)) nsp = cls(':'.join(fqnp))

View File

@ -882,12 +882,15 @@ class Actor:
except BaseException as startup_err: except BaseException as startup_err:
with trio.CancelScope(shield=True): with trio.CancelScope(shield=True):
# `MsgpackTransport.send()` closes its stream when # `MsgpackTransport.send()` shields length-prefixed frame
# cancellation interrupts the length-prefixed write # publication until complete, then checkpoints pending
# because an unknown prefix may already be sent. A # cancellation before returning. Thus `start_published`
# connected channel means cancellation happened before # can remain false after a complete `Start` reached the
# that write or after it completed, so `_cancel_task` # wire. If the send's own deadline catches a partial
# is protocol-safe (and a no-op if `Start` was unsent). # frame, it closes the stream. A connected channel means
# cancellation happened before the write or after frame
# completion, so `_cancel_task` is protocol-safe (and
# a no-op when `Start` was unsent).
if ( if (
cancel_on_startup cancel_on_startup
and and