Skip to content

Make ship_and_run primitives safe for concurrent pod fan-out - #2

Open
protereus wants to merge 1 commit into
banodoco:mainfrom
protereus:feat/pod-fanout-safety
Open

Make ship_and_run primitives safe for concurrent pod fan-out#2
protereus wants to merge 1 commit into
banodoco:mainfrom
protereus:feat/pod-fanout-safety

Conversation

@protereus

Copy link
Copy Markdown

Closes #1.

Changes

  • ShipAndRunResult.error (+ raise_if_error()) — ship_and_run/ship_and_run_detached now capture generic exceptions instead of raising past their existing finally cleanup.
  • ship_and_run_many() — concurrent fan-out over ship_and_run, one pod per script, via gather(..., return_exceptions=True). local_roots is required (not None-per-job default) since ship_and_run's own local_root has no such default and unconditionally uploads from it.
  • PodGuard.terminate(verify=True) — optional post-terminate status re-check, opt-in, defaults to today's behavior.

All additive and backward-compatible — no existing caller or test needed to change.

Testing

pytest -q: 133 passed, 6 skipped (was 124/6 on main; 9 new tests, zero regressions). New tests cover exception capture, the fan-out starvation property (a failing job doesn't block/lose a concurrent success), the local_roots requirement, and terminate's verify path.

ship_and_run/ship_and_run_detached already guaranteed pod cleanup via
finally, but could still raise past it (only CancelledError was caught) --
fine for one pod, but the moment several run concurrently via
asyncio.gather, one raised exception surfaces to the caller immediately
while sibling tasks keep running unmonitored in the background. Add
ShipAndRunResult.error (+ raise_if_error() to opt back into today's
behavior) and capture generic exceptions into it instead.

Add ship_and_run_many() as a thin concurrent fan-out on top, using
gather(..., return_exceptions=True) so a failing job never starves or
loses a sibling's result. local_roots is required (not defaulting to
None-per-job) since ship_and_run's own local_root has no such default and
unconditionally uploads from it -- a None default here would have made
every job silently fail with an AttributeError instead of failing loudly
at the call boundary.

Add PodGuard.terminate(verify=True) for an optional post-terminate
status re-check, opt-in and fully backward compatible with existing
zero-arg call sites.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@protereus
protereus force-pushed the feat/pod-fanout-safety branch from 690a687 to 8a21f71 Compare July 22, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Concurrent pod fan-out: ship_and_run primitives can raise past cleanup

1 participant