Centralize `Context` registry removal
Derive the `Actor._contexts` key from each `Context` in one idempotent `Actor._drop_context()` helper instead of reconstructing the peer UID and CID at every teardown site. Use the helper for caller-side context exit and preserve a strict identity assertion when the callee-side RPC task deregisters itself. Keep channel closure and cancellation shielding with their existing lifecycle owners. Caught-during: review remediation Found-via: staged P2 lifecycle review Review: PR #481 (opencode) https://github.com/goodboy/tractor/pull/481#pullrequestreview-4956692120 Prompt-IO: ai/prompt-io/opencode/20260818T193002Z_bf06b4f8_prompt_io.md (this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))drop_ria_nursery
parent
4d07965a2a
commit
754458ee7d
|
|
@ -0,0 +1,37 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
session: ses_3e4c90d3eafeqHEtRYSIHgHhpA
|
||||||
|
timestamp: 2026-08-18T19:30:02Z
|
||||||
|
git_ref: bf06b4f8
|
||||||
|
scope: code
|
||||||
|
substantive: true
|
||||||
|
raw_file: 20260818T193002Z_bf06b4f8_prompt_io.raw.md
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prompt
|
||||||
|
|
||||||
|
Distill repeated `Actor._contexts.pop()` machinery into a wrapper like
|
||||||
|
the RPC-task registration helper so future teardown sites do not keep
|
||||||
|
reconstructing the context-registry key independently. Preserve the
|
||||||
|
existing lifecycle-specific cleanup behavior.
|
||||||
|
|
||||||
|
## Response summary
|
||||||
|
|
||||||
|
Add idempotent `Actor._drop_context()` registry removal keyed from the
|
||||||
|
context's own channel and CID. Use it for caller context teardown and
|
||||||
|
the strict callee-side RPC deregistration path.
|
||||||
|
|
||||||
|
## Files changed
|
||||||
|
|
||||||
|
- `tractor/runtime/_runtime.py` - own context-registry removal.
|
||||||
|
- `tractor/runtime/_rpc.py` - use the helper for callee teardown.
|
||||||
|
- `tractor/_context.py` - use the helper after caller teardown.
|
||||||
|
|
||||||
|
## Human edits
|
||||||
|
|
||||||
|
The human identified the repeated registry-pop code and requested a
|
||||||
|
central primitive analogous to `_register_rpc_task()`. The agent first
|
||||||
|
suggested an async helper that also closed receive channels; the final
|
||||||
|
design was narrowed to registry removal only so each lifecycle owner
|
||||||
|
retains its existing closure, debugger, shielding, and error policy.
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
model: openai/gpt-5.6-sol
|
||||||
|
service: opencode
|
||||||
|
timestamp: 2026-08-18T19:30:02Z
|
||||||
|
git_ref: bf06b4f8
|
||||||
|
diff_cmd: git diff HEAD~1..HEAD
|
||||||
|
---
|
||||||
|
|
||||||
|
Repeated teardown sites reconstruct the `Actor._contexts` registry
|
||||||
|
key from a portal channel and context ID before popping it. Add an
|
||||||
|
idempotent actor-owned helper deriving the key from the context itself,
|
||||||
|
then route caller and callee context teardown through that helper.
|
||||||
|
|
||||||
|
> `git diff HEAD~1..HEAD -- tractor/runtime/_runtime.py tractor/runtime/_rpc.py tractor/_context.py`
|
||||||
|
|
||||||
|
Keep receive-channel closure and cancellation shielding in each
|
||||||
|
lifecycle owner so the helper centralizes registry machinery without
|
||||||
|
changing their teardown ordering.
|
||||||
|
|
@ -2625,10 +2625,7 @@ async def open_context_from_portal(
|
||||||
f'uid: {uid}\n'
|
f'uid: {uid}\n'
|
||||||
f'cid: {ctx.cid}\n'
|
f'cid: {ctx.cid}\n'
|
||||||
)
|
)
|
||||||
portal.actor._contexts.pop(
|
portal.actor._drop_context(ctx)
|
||||||
(uid, ctx.cid),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
|
|
||||||
# XXX revert to prior IPC-task-ctx scope
|
# XXX revert to prior IPC-task-ctx scope
|
||||||
_ctxvar_Context.reset(prior_ctx_tok)
|
_ctxvar_Context.reset(prior_ctx_tok)
|
||||||
|
|
|
||||||
|
|
@ -879,10 +879,8 @@ async def _invoke(
|
||||||
# don't pop the local context until we know the
|
# don't pop the local context until we know the
|
||||||
# associated child isn't in debug any more
|
# associated child isn't in debug any more
|
||||||
await debug.maybe_wait_for_debugger()
|
await debug.maybe_wait_for_debugger()
|
||||||
ctx: Context = actor._contexts.pop((
|
dropped_ctx: Context|None = actor._drop_context(ctx)
|
||||||
chan.aid.uid,
|
assert dropped_ctx is ctx
|
||||||
cid,
|
|
||||||
))
|
|
||||||
|
|
||||||
logmeth: Callable = log.runtime
|
logmeth: Callable = log.runtime
|
||||||
merr: Exception|None = ctx.maybe_error
|
merr: Exception|None = ctx.maybe_error
|
||||||
|
|
|
||||||
|
|
@ -753,6 +753,23 @@ class Actor:
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
def _drop_context(
|
||||||
|
self,
|
||||||
|
ctx: Context,
|
||||||
|
) -> Context|None:
|
||||||
|
'''
|
||||||
|
Remove `ctx` from this actor's IPC context registry.
|
||||||
|
|
||||||
|
Teardown paths can converge after normal return, cancellation
|
||||||
|
or startup failure, so registry removal is idempotent.
|
||||||
|
|
||||||
|
'''
|
||||||
|
peer_uid: tuple[str, str] = ctx.chan.aid.uid
|
||||||
|
return self._contexts.pop(
|
||||||
|
(peer_uid, ctx.cid),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
async def start_remote_task(
|
async def start_remote_task(
|
||||||
self,
|
self,
|
||||||
chan: Channel,
|
chan: Channel,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue