pub struct DispatchLoop<W: WalWriter, H: ExecutorHandler, C: Clock = SystemClock, I: ExecutorIdentity = LocalExecutorIdentity> { /* private fields */ }Expand description
The core dispatch loop that composes all engine primitives.
Workers execute handler logic via tokio::task::spawn_blocking and send
results back through an unbounded MPSC channel. All WAL mutation authority
remains exclusively owned by the dispatch loop — workers never touch the WAL.
The I: ExecutorIdentity generic defaults to LocalExecutorIdentity so
existing construction sites don’t need changes for v0.x. Sprint 4 remote
actors will supply their own identity via this parameter.
Implementations§
Source§impl<W: WalWriter, H: ExecutorHandler + 'static, C: Clock> DispatchLoop<W, H, C>
impl<W: WalWriter, H: ExecutorHandler + 'static, C: Clock> DispatchLoop<W, H, C>
Sourcepub fn new(
authority: StorageMutationAuthority<W, ReplayReducer>,
handler: H,
clock: C,
config: DispatchConfig,
) -> Result<Self, DispatchError>
pub fn new( authority: StorageMutationAuthority<W, ReplayReducer>, handler: H, clock: C, config: DispatchConfig, ) -> Result<Self, DispatchError>
Creates a new dispatch loop.
§Errors
Returns DispatchError::InvalidBackoffConfig if the backoff strategy
configuration is invalid (e.g., exponential base exceeds max).
Sourcepub fn projection(&self) -> &ReplayReducer
pub fn projection(&self) -> &ReplayReducer
Returns a reference to the projection (current state view).
Sourcepub async fn tick(&mut self) -> Result<TickResult, DispatchError>
pub async fn tick(&mut self) -> Result<TickResult, DispatchError>
Advances the state machine one step.
A tick performs: 0a. Drain workflow submissions from handlers (non-blocking) 0b. Drain completed worker results (non-blocking) 0c. Cascade hierarchy cancellations to descendants of canceled tasks 0c-gc. GC terminal tasks from in-memory data structures 0d. Derive new cron runs to maintain the rolling window (workflow feature) 0f. Check actor heartbeat timeouts (actor feature)
- Heartbeat in-flight leases approaching expiry
- Check engine paused state — skip if paused
- Promote Scheduled → Ready (time-based)
- Promote RetryWait → Ready (backoff-based)
- Select ready runs (priority-FIFO-RunId)
- For each selected: check concurrency key gate → lease → dispatch (spawn worker)
Sourcepub async fn run_until_idle(&mut self) -> Result<RunSummary, DispatchError>
pub async fn run_until_idle(&mut self) -> Result<RunSummary, DispatchError>
Loops tick() until no work remains (no in-flight, no promotions, no dispatches).
Sourcepub fn start_drain(&mut self)
pub fn start_drain(&mut self)
Begins graceful drain: stops promoting and dispatching new work, but continues processing in-flight results and heartbeating leases.
Sourcepub async fn drain_until_idle(
&mut self,
timeout: Duration,
) -> Result<RunSummary, DispatchError>
pub async fn drain_until_idle( &mut self, timeout: Duration, ) -> Result<RunSummary, DispatchError>
Drains in-flight work until idle or the timeout expires.
Sourcepub fn submit_task(&mut self, spec: TaskSpec) -> Result<(), DispatchError>
pub fn submit_task(&mut self, spec: TaskSpec) -> Result<(), DispatchError>
Submits a new task and derives initial runs.
Sourcepub fn declare_dependency(
&mut self,
task_id: TaskId,
prereqs: Vec<TaskId>,
) -> Result<(), DispatchError>
pub fn declare_dependency( &mut self, task_id: TaskId, prereqs: Vec<TaskId>, ) -> Result<(), DispatchError>
Declares a DAG dependency: task_id may not promote until all prereqs complete.
Validates cycle-freedom and prerequisite existence before WAL-appending.
Consumes the dispatch loop and returns the mutation authority.