From c62f93a8fb8158809118ce7ba17b10610b338d95 Mon Sep 17 00:00:00 2001 From: goodboy Date: Mon, 6 Jul 2026 14:31:34 -0400 Subject: [PATCH] Doc the #477 migration outcome + one-shot-acm sketch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fold the endeavour's resolution into the plan doc + log the session per prompt-io policy, - `ria_nursery_removal_plan.md`: RESOLVED section — migrate everything, remove the API; the migration-pattern table (blocking / fire-and-forget / fan-out / collect-don't-cancel / mutual-rendezvous), the semantic deltas (cancel-on-first + `collapse_eg()` chain collapse vs the old teardown-reap BEG), the excision inventory and the structural dissolution of the reap-hang class. - adds the `to_actor.open_one_shot()` follow-up sketch: an `@acm` + private task-nursery over the existing blocking `run()` — done-`trio.Event` as a result memo (NOT a cancel-relay), no `Portal` in the iface, errors always propagate at scope exit; zero `_supervise` coupling. - prompt-io entry `20260706T172818Z_ad42871e` (+ raw diff-ref companion) covering commits `d01a2123..ad42871e`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code --- ai/conc-anal/ria_nursery_removal_plan.md | 93 ++++++++++++++++++- .../20260706T172818Z_ad42871e_prompt_io.md | 81 ++++++++++++++++ ...20260706T172818Z_ad42871e_prompt_io.raw.md | 39 ++++++++ 3 files changed, 209 insertions(+), 4 deletions(-) create mode 100644 ai/prompt-io/claude/20260706T172818Z_ad42871e_prompt_io.md create mode 100644 ai/prompt-io/claude/20260706T172818Z_ad42871e_prompt_io.raw.md diff --git a/ai/conc-anal/ria_nursery_removal_plan.md b/ai/conc-anal/ria_nursery_removal_plan.md index 135b4c4d..bad6ded7 100644 --- a/ai/conc-anal/ria_nursery_removal_plan.md +++ b/ai/conc-anal/ria_nursery_removal_plan.md @@ -367,9 +367,94 @@ user's failing-test-first convention). The poll-based reap fix in `_supervise.py` is UNCOMMITTED and likely SUPERSEDED by the re-scoping — do NOT land it as-is. +## RESOLVED (2026-07-06): migrate everything, remove the API + +The PAUSED re-assessment concluded decisively: rather than +re-scope `_reap_ria_portals` (or bolt any hack onto it), the +`run_in_actor()` API itself was REMOVED — its non-blocking +"result at teardown" semantic predates streaming and confused +more than it served. Every in-repo caller was migrated +per-file/-group (each its own commit, each gated): + +- tests: `test_infected_asyncio` `test_runtime` `test_rpc` + `test_spawning` `test_pubsub` `test_registrar` + `test_cancellation` (3 groups) `test_advanced_streaming`. +- examples: 4 non-debugging + all 8 `debugging/` REPL scripts + (debugger suite byte-identical green, 28p/6s). +- docs: 8 rst pages + the `experimental/_pubsub` docstring. + +Migration patterns (the `run_in_actor` shape -> successor): + +- blocking result -> `to_actor.run(fn, an=an, ...)` +- fire-&-forget/forever -> bg `to_actor.run()` task in a local + `trio` task-nursery (or `start_actor` + + bg `Portal.run()` when a portal + handle is needed) +- concurrent fan-out -> N bg `to_actor.run()` tasks / or + `gather_contexts([p.open_context(..)])` +- reap-all-error-collect -> the "collect don't cancel" pattern: + each one-shot catches + stashes its + `RemoteActorError`, group raised + after the task-nursery joins (see + `examples/debugging/multi_subactors.py`) +- mutual-rendezvous -> peers must OUTLIVE both dialogs: + `start_actor()` daemons + concurrent + `Portal.run()`s + explicit + `an.cancel()` (eager one-shot reap + races the slower peer's dial of the + winner's dead sockaddr; found via + `test_trynamic_trio` flake). + +Semantic deltas (tests loosened accordingly): + +- teardown-reap-all BEG-of-N is GONE: local task-nurseries are + cancel-on-first, raced siblings' `Cancelled`s are absorbed, + and the runtime's `collapse_eg()` unwraps every single-member + group at each actor boundary — a fully-raced nested tree + relays a bare (annotated) `RemoteActorError` chain. +- `test_multierror_fast_nursery` deleted (pure reap-stress); + `test_nested_multierrors` re-purposed as deep-tree + cancel-cascade stress w/ a race-tolerant shape walk. + +Final excision (after zero callers remained): `run_in_actor()`, +`._cancel_after_result_on_exit`, `_reap_ria_portals()`, +`Portal._submit_for_result/._expect_result_ctx/ +.wait_for_result()/.result()`, `exhaust_portal()`, +`cancel_on_completion()`, `NoResult` — net -402 lines. The +reap-hang class (unbounded `wait_for_result` in machinery +scope) dissolves structurally: the only result-wait left lives +in the caller's task inside its own cancel-scope; the +`d1fb4a1a` anti-hang guard test passes by construction. The +poll-vs-`proc_waiter` debate is moot as predicted. + +## Follow-up sketch: `to_actor.open_one_shot()` (run-async parity) + +If deferred-result parity is ever wanted, the design that needs +NO runtime coupling, NO returned `Portal` and NO cancel-relay +`trio.Event` machinery: + + async with to_actor.open_one_shot( + fn, an=an, **kws, + ) as one_shot: + ... # concurrent caller work + val = await one_shot.wait() # optional; errors always + # propagate at scope exit + +an `@acm` that opens a private task-nursery, `start_soon`s ONE +task running the existing blocking `run()` and stashes the +value in a slot + sets a done-`trio.Event` (a memo, not a +cancel relay). Cancellation = plain scope-cancel of the acm's +nursery (the parked `Portal.run()` unwinds via `Cancelled`, the +shielded `cancel_actor()` reap still runs); a child error +raises into the acm scope so an un-`wait()`ed one-shot can +never silently drop its error. i.e. the old reaper's job is +done by scoping, not machinery. ~40 lines, all in +`to_actor/_api.py`, zero `_supervise` involvement. + ## Verification gate -- `tests/test_cancellation.py test_spawning.py test_local.py - test_rpc.py` on `trio` + `mp_spawn` + `mp_forkserver` - backends, then full suite; `tests/devx/test_debugger.py` - for risk 3. +- per-migration-commit module gates on `trio` (+ `mp_spawn` + spot-gates incl. `test_infected_asyncio` per the B2 lesson); + `tests/devx/test_debugger.py` for the REPL flows. +- full suite on `trio` + `mp_spawn` at branch tip + CI matrix + via draft PR #484. diff --git a/ai/prompt-io/claude/20260706T172818Z_ad42871e_prompt_io.md b/ai/prompt-io/claude/20260706T172818Z_ad42871e_prompt_io.md new file mode 100644 index 00000000..bb355012 --- /dev/null +++ b/ai/prompt-io/claude/20260706T172818Z_ad42871e_prompt_io.md @@ -0,0 +1,81 @@ +--- +model: claude-fable-5 +service: claude +session: 6db64ac6-6986-4505-9343-df4ee31e67db +timestamp: 2026-07-06T17:28:18Z +git_ref: ad42871e +scope: code +substantive: true +raw_file: 20260706T172818Z_ad42871e_prompt_io.raw.md +--- + +## Prompt + +Resuming the `drop_ria_nursery` (wkt) branch after the human's +review pause at `ba4af0ad`, with the directive: + +> we need to resolve the remaining outstandings ... to finish +> this endeavour we ideally, +> - finish the ria-tn hoist into the machinery in `to_actor` if +> possible. +> - avoid supporting the `.run_in_actor()` non-blocking API +> going forward other then if we can re-wrap `to_actor.run()` +> per prior discussion with opus4.8. +> - get the test harness completely green locally and in CI - +> AND ESPECIALLY without any hangs due to the "the old +> spawn-backend reaper raced `soft_kill()`'s scope-cancel" +> - update all docs to reflect these changes once we're happy. + +plus mid-flight additions: + +> make sure both all the test and example code uses the naming +> `an: ActorNursery` for variable names + +> where we at in terms of a potential hackaround design for +> supporting a to_actor.run_async() ... without requiring the +> same malarky ... with a `trio.Event` relay ... i'm totes fine +> with rejigging the iface to NOT return a Portal as well. + +## Response summary + +Completed the entire #477 `run_in_actor` removal on +`drop_ria_nursery` (16 commits this session), gated per-commit: + +- ported the remaining `test_cancellation` groups + (`some_cancels_all`, `nested_multierrors`+`spawn_and_error`, + SIGINT + sync-sleep) — one-shots become concurrent + `to_actor.run()` tasks in local task-nurseries; BEG-shape + assertions loosened for cancel-on-first + the runtime's + `collapse_eg()` single-member unwrap (a fully-raced nested + tree relays a bare annotated `RemoteActorError` chain). +- fixed a pre-existing `UnboundLocalError` (`timeout` `match` + had no default arm for non-trio/MTF backends). +- ported `test_dynamic_pub_sub`, 4 non-debugging examples, all + 8 `debugging/` examples (debugger suite byte-identical, + 28p/6s; `multi_subactors` introduces the "collect don't + cancel" reap-all replacement pattern), 8 docs pages + the + `experimental/_pubsub` docstring. +- EXCISED the API + cluster: `run_in_actor`, + `_reap_ria_portals`, `_cancel_after_result_on_exit`, + `Portal._submit_for_result/_expect_result_ctx/ + wait_for_result/result`, `exhaust_portal`, + `cancel_on_completion`, `NoResult` — net -402 lines. The + reap-hang class dissolves structurally (result-waits now only + in caller task-scope). +- found + fixed a real migration race: mutual-rendezvous peers + (`test_trynamic_trio`, `a_trynamic_first_scene.py`) flaked + because an eagerly-reaped one-shot dies while its peer still + dials the registry-resolved (dead) sockaddr — such peers now + pin lifetimes via `start_actor()` + concurrent `Portal.run()` + + explicit `an.cancel()`. +- `an: ActorNursery` naming sweep across tests/examples (±82 + lines, scoped renames, prose untouched). +- parked a `to_actor.open_one_shot()` design sketch (acm + + private task-nursery over blocking `run()`; done-Event as + memo not cancel-relay; no Portal) in the plan doc. + +## Files changed + +See commits `d01a2123..ad42871e` on `drop_ria_nursery` +(tests, examples, docs, `tractor/{runtime,spawn,to_actor,msg}` ++ `_exceptions/_context/experimental`). diff --git a/ai/prompt-io/claude/20260706T172818Z_ad42871e_prompt_io.raw.md b/ai/prompt-io/claude/20260706T172818Z_ad42871e_prompt_io.raw.md new file mode 100644 index 00000000..b6aa9d73 --- /dev/null +++ b/ai/prompt-io/claude/20260706T172818Z_ad42871e_prompt_io.raw.md @@ -0,0 +1,39 @@ +--- +model: claude-fable-5 +service: claude +timestamp: 2026-07-06T17:28:18Z +git_ref: ad42871e +diff_cmd: git diff ba4af0ad..ad42871e +--- + +# Raw AI output (diff-ref mode) + +This session's output spans the 16 migration/excision commits +`d01a2123..ad42871e` on `drop_ria_nursery`; per diff-ref mode +the verbatim content is reachable via the pointer below. + +## Generated files + +> `git diff ba4af0ad..ad42871e` + +Commit-wise (each `Gate:`-footed msg documents its own module +gate): + +- `d01a2123` port `test_some_cancels_all` +- `697c6152` fix unbound `timeout` (non-trio/MTF `match` arm) +- `fa8799d5` port `test_nested_multierrors` +- `f11754ce` port SIGINT + sync-sleep cancel tests +- `cb6202e3` port `test_dynamic_pub_sub` +- `d8af5f12` port non-debugging examples +- `a3057cb2` port debugging examples (+ `test_debugger` + nested-nurseries final-shape expectations) +- `d6bed7c4` port docs (8 rst pages) +- `07e1669e` fix stale `@pub` docstring example +- `2a59cefb` REMOVE `run_in_actor()` + the ria reap cluster + (net -402 lines) +- `a297a32a` fix mutual-rendezvous premature-reap race +- `ad42871e` `an: ActorNursery` naming sweep + +Plan/design record updated in +`ai/conc-anal/ria_nursery_removal_plan.md` (RESOLVED section + +the `to_actor.open_one_shot()` follow-up sketch).