Skip to content

design: dynamic supervisor (rank 12a) - #245

Draft
unbalancedparentheses wants to merge 54 commits into
mainfrom
design/dynamic-supervisor
Draft

unbalancedparentheses wants to merge 54 commits into
mainfrom
design/dynamic-supervisor

Conversation

@unbalancedparentheses

@unbalancedparentheses unbalancedparentheses commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Design only (no implementation) for ROADMAP rank 12a: a dynamic supervisor matching OTP simple_one_for_one and Elixir DynamicSupervisor.

Revision 2 applies the maintainer's decisions on Q1-Q7 and resolves the first Codex and agy reviews (every P0/P1, plus both P2s). Per-finding resolutions are in the doc's "Review resolutions" section.

Decisions applied

  • Q1: one control loop serialises starts, exit handling and terminate_child, as OTP; ethrex's handshake moves out of started().
  • Q2: typed template only.
  • Q3: Elixir defaults (3 per 5 s), backoff opt-in, max_children = None (Some(0) allowed).
  • Q4: transferable native-capacity reservation per slot; pinned groups keep affinity only.
  • Q5: exhaustion exits Shutdown with diagnostics; static nested supervisors in a follow-up PR.
  • Q6: static terminate_child in a follow-up.
  • Q7: Rejected { reason, args } before admission; Aborted and FailedToStart afterwards.

Main review-driven changes

  • Stuck children: one that was retiring anyway fails only itself; the supervisor fails only for a stuck child it would restart, or during shutdown (agy P0).
  • Model rewritten: serialised loop, explicit reservation/stamp/refund, history variables computed outside the actions, accumulating alive, RestartFollowsPolicy in both directions, first-start rules, terminate resolution, stuck isolation.
  • Terminate key = last published ActorId, kept through failed replacements; terminate_slot.
  • Client mapping: handshake out of started(), the raw writer task becomes an owned helper, teardown owners for skipped stopped(), monitor guard in Handler<Down>.

TLC (fede, TLC 2.19, 4 workers, nice 19)

Config Distinct states Depth Time Result
MCDynamicSupervisor (per PR, safety) 3,459,556 33 39 s no error
MCDynamicSupervisorLive (per PR, liveness) 1,628,738 33 5m21s no error
MCDynamicSupervisorZero (per PR, budget 0) 589,159 22 1m23s no error
MCDynamicSupervisorDeep (weekly) 31,620,430 42 5m06s no error

All 27 named negative controls (25 safety, 2 liveness) produce their counterexample on their named property, run one at a time, 1-5 s each.

…aller fairness, backoff switch, fan-out refinement, ignore, 40 controls)
…tartError, Init::continue_with, StartOptions)
… NoAbort on a passing deadline-free config (Codex round 3, 2)
…tate, not Down reason, suppresses retries (Codex round 3, 3)
…rtOutcome/ChildStart mismatches fixed (agy round 3, 1)
…st published child, no ticket for directly consumed exits, fan-out ends on its last signal (agy round 3, 2)
…n); smaller per-PR configs; controls target the broad ones

This branch has not been deployed

No deployments
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.

1 participant