From e42ecb559d16720c85a55a887083a7c060cbe9b4 Mon Sep 17 00:00:00 2001 From: goodboy Date: Mon, 24 Aug 2026 21:56:00 -0400 Subject: [PATCH] Use `Aid` keys for child reap state The fresh reap-coordination maps still used legacy `.uid` tuples even though process monitors and channels carry complete `Aid` identities. This extended the legacy key format into new private state. Key both reap maps by `Aid` and derive `.uid` only when accessing the existing `_children` map. UUID-based `Aid` hashing lets the subactor and decoded channel identities resolve the same synchronization state. Update registration tests to exercise the full identity keys. Review: PR #481 (goodboy) https://github.com/goodboy/tractor/pull/481#pullrequestreview-5012942328 Prompt-IO: ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.md (this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`)) --- .../20260824T233957Z_5327b25e_prompt_io.md | 36 +++++++++++++++++++ ...20260824T233957Z_5327b25e_prompt_io.raw.md | 27 ++++++++++++++ tests/test_to_actor.py | 10 +++--- tractor/runtime/_supervise.py | 30 +++++++++------- tractor/spawn/_spawn.py | 2 +- 5 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.md create mode 100644 ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.raw.md diff --git a/ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.md b/ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.md new file mode 100644 index 00000000..e25843e1 --- /dev/null +++ b/ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.md @@ -0,0 +1,36 @@ +--- +model: openai/gpt-5.6-sol +service: opencode +session: d9d7df2c-7044-463f-8768-ec024718eac9 +timestamp: 2026-08-24T23:39:57Z +git_ref: 5327b25e +scope: code +substantive: true +raw_file: 20260824T233957Z_5327b25e_prompt_io.raw.md +--- + +## Prompt + +Continue PR #481 review remediation after committing the debugger-state +sampler. The human selected "keep" for the paired review request to use +`Aid` objects as keys in the newly added reap-coordination maps. + +## Response summary + +Migrate only `ActorNursery._child_reap_requests` and +`ActorNursery._child_reaped` to `Aid` keys. Preserve the legacy +`ActorNursery._children` `.uid` key and pass full actor identities +through the narrow process-monitor bookkeeping path. + +## Files changed + +- `tractor/runtime/_supervise.py` - key fresh reap maps by `Aid`. +- `tractor/spawn/_spawn.py` - pass `Aid` into completed-reap cleanup. +- `tests/test_to_actor.py` - exercise `Aid` registration keys. + +## Human edits + +The human explicitly selected "keep" after reviewing the scope, +performance, and mutability tradeoffs. The human retained the legacy +tuple key for `_children` and accepted `Aid` for only the two fresh +private mappings. No direct source-line edits were made by the human. diff --git a/ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.raw.md b/ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.raw.md new file mode 100644 index 00000000..eefd2437 --- /dev/null +++ b/ai/prompt-io/opencode/20260824T233957Z_5327b25e_prompt_io.raw.md @@ -0,0 +1,27 @@ +--- +model: openai/gpt-5.6-sol +service: opencode +timestamp: 2026-08-24T23:39:57Z +git_ref: 5327b25e +diff_cmd: git diff HEAD~1..HEAD +--- + +Implement the approved PR #481 review update which uses `Aid` keys for +the two fresh `ActorNursery` reap-coordination maps while preserving the +legacy `.uid` key for `ActorNursery._children`. + +> `git diff HEAD~1..HEAD -- tractor/runtime/_supervise.py` + +Type and access `_child_reap_requests` and `_child_reaped` by `Aid`. +Pass full actor identities through registration, cancellation, and +completed-reap bookkeeping, deriving `.uid` only for `_children`. + +> `git diff HEAD~1..HEAD -- tractor/spawn/_spawn.py` + +Forward `subactor.aid` when publishing completed process teardown. + +> `git diff HEAD~1..HEAD -- tests/test_to_actor.py` + +Update deterministic registration tests to exercise `Aid` map keys. + +Run focused registration/reaping tests and the full `to_actor` suite. diff --git a/tests/test_to_actor.py b/tests/test_to_actor.py index 9fddb224..61216cc7 100644 --- a/tests/test_to_actor.py +++ b/tests/test_to_actor.py @@ -431,8 +431,8 @@ def test_late_child_registration_observes_cancel(): proc, None, ) - assert an._child_reap_requests[aid.uid] is reap_request - assert an._child_reaped[aid.uid] is reaped + assert an._child_reap_requests[aid] is reap_request + assert an._child_reaped[aid] is reaped def test_mp_late_registration_never_starts_process( @@ -521,9 +521,11 @@ def test_late_child_reap_registration_is_released(): an._child_reaped = {} an._join_procs.set() - reap_request, _ = an._register_child_reap( - ('late_child', 'uid'), + aid = tractor.msg.Aid( + name='late_child', + uuid='uid', ) + reap_request, _ = an._register_child_reap(aid) assert reap_request.is_set() diff --git a/tractor/runtime/_supervise.py b/tractor/runtime/_supervise.py index 6e09c65f..94724257 100644 --- a/tractor/runtime/_supervise.py +++ b/tractor/runtime/_supervise.py @@ -46,6 +46,7 @@ from ..log import ( get_logger, get_loglevel, ) +from ..msg import Aid from ._runtime import Actor from ._portal import Portal from ..trionics import ( @@ -246,11 +247,11 @@ class ActorNursery: self._join_procs = trio.Event() self._child_reap_requests: dict[ - tuple[str, str], + Aid, trio.Event, ] = {} self._child_reaped: dict[ - tuple[str, str], + Aid, trio.Event, ] = {} self._at_least_one_child_in_debug: bool = False @@ -319,7 +320,7 @@ class ActorNursery: def _register_child_reap( self, - uid: tuple[str, str], + aid: Aid, ) -> tuple[trio.Event, trio.Event]: ''' Register a child monitor's process-reap events. @@ -327,8 +328,8 @@ class ActorNursery: ''' reap_request = trio.Event() reaped = trio.Event() - self._child_reap_requests[uid] = reap_request - self._child_reaped[uid] = reaped + self._child_reap_requests[aid] = reap_request + self._child_reaped[aid] = reaped if self._join_procs.is_set(): reap_request.set() return reap_request, reaped @@ -343,13 +344,14 @@ class ActorNursery: Atomically publish one child and its reap coordination. ''' - uid: tuple[str, str] = subactor.aid.uid + aid: Aid = subactor.aid + uid: tuple[str, str] = aid.uid self._children[uid] = ( subactor, proc, portal, ) - reap_request, reaped = self._register_child_reap(uid) + reap_request, reaped = self._register_child_reap(aid) return ( reap_request, reaped, @@ -369,18 +371,19 @@ class ActorNursery: def _mark_child_reaped( self, - uid: tuple[str, str], + aid: Aid, ) -> None: ''' Publish completed child-process teardown to its waiter. ''' + uid: tuple[str, str] = aid.uid self._children.pop(uid, None) reap_request: trio.Event|None = ( - self._child_reap_requests.pop(uid, None) + self._child_reap_requests.pop(aid, None) ) reaped: trio.Event|None = self._child_reaped.pop( - uid, + aid, None, ) assert ( @@ -399,14 +402,15 @@ class ActorNursery: Cancel, join and unregister one nursery-owned child. ''' - uid: tuple[str, str] = portal.channel.aid.uid + aid: Aid = portal.channel.aid + uid: tuple[str, str] = aid.uid child_entry = self._children.get(uid) if child_entry is None: return subactor, proc, _ = child_entry - reap_request: trio.Event = self._child_reap_requests[uid] - reaped: trio.Event = self._child_reaped[uid] + reap_request: trio.Event = self._child_reap_requests[aid] + reaped: trio.Event = self._child_reaped[aid] with trio.CancelScope(shield=True): try: diff --git a/tractor/spawn/_spawn.py b/tractor/spawn/_spawn.py index 1cee9637..39686b9c 100644 --- a/tractor/spawn/_spawn.py +++ b/tractor/spawn/_spawn.py @@ -460,7 +460,7 @@ async def new_proc( proc_kwargs=proc_kwargs ) finally: - actor_nursery._mark_child_reaped(subactor.aid.uid) + actor_nursery._mark_child_reaped(subactor.aid) # NOTE: bottom-of-module to avoid a circular import since the