Expand description
Phase-end trigger registry — content-agnostic callbacks
that fire after every phase completion or failure. Used by
the watch=plots / watch=report CLI flags to keep an
external view (plot image, report html) up-to-date as the
run progresses.
Phase-end trigger registry.
A simple event/callback registry that any subsystem can
attach a callback to. Callbacks fire after every
phase_completed and phase_failed event from the
executor. Triggers are dispatched on a background worker
thread so a slow callback (e.g. re-rendering a plot
against the live session.db) never blocks the run loop.
§Why a separate registry instead of new RunObserver
methods
RunObserver is the surface for display observers (TUI,
log-only, stderr). A trigger is behavioral — it runs work
in response to lifecycle events without contributing to
display rendering. Trying to merge the two via a generic
observer interface forces every plot author to implement
the noisy phase_starting / set_status_line / reporters
surface. The registry is the focused alternative.
§Lifecycle
- [
register] adds a trigger and returns a [TriggerId]. - [
unregister] removes a trigger by id (no-op if absent). - The executor calls [
fire_phase_completed] / [fire_phase_failed] immediately after the observer’s matching callback. Triggers run on a single worker thread in FIFO registration order so a panic in one trigger doesn’t take down the others (each call iscatch_unwind-guarded).
§Synchronization
The registry sits behind a std::sync::Mutex for
registration; the worker thread snapshots the trigger
list on each event so a registration / unregistration mid-
event won’t dirty the dispatch. Total cost per phase end
is one channel send + one Vec clone of Arc<Trigger>.
Structs§
- Phase
EndEvent - What the executor knows about a finished phase.
- Trigger
Id - Opaque registration handle returned by
register. Pass tounregisterto remove the trigger.
Enums§
- Phase
Outcome - Outcome flavor — success, failure, or skip-equivalent.
Traits§
- Phase
EndTrigger - Trigger callback. Implementors fire whenever a phase completes (success or failure). The implementation should be cheap to set up — long work runs on the worker thread, not the executor.
Functions§
- fire_
phase_ completed - Fire the trigger chain for a successful phase. Called by
the executor right after
observer.phase_completed(...). - fire_
phase_ failed - Fire the trigger chain for a failed phase. Called by the
executor right after
observer.phase_failed(...). - register
- Register a phase-end trigger. Returns a
TriggerIdthe caller can pass tounregisterlater. Idempotent within a single registration — the same trigger object registered twice fires twice. - unregister
- Remove a previously-registered trigger. No-op when the id doesn’t match anything currently registered (already removed, never registered, or freed by another caller).