Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Basic lifecycle

An FSM puts lifecycle topology in the model. It declares an initial state, allowed transitions, and a reachable final state.

YAML model

quent: alpha
model: finite_state_machine

fsms:
  Job:
    states:
      queued:
        initial: true
        to: [loading_input, restoring_checkpoint]
      loading_input:
        to: [running]
      restoring_checkpoint:
        to: [running]
      running:
        to: [completed]
      completed: {}

The parser rejects missing initial states, unreachable states, invalid targets, and FSMs without a reachable final state. It also derives event cardinality from the topology.

Instrumentation API

Entering a state emits its generated event. The generated Rust API represents the current FSM state in the handle’s type. Each transition consumes that handle and returns a handle for the target state. Only transitions allowed from the current state are available as methods, so an invalid transition does not compile. This pattern is called typestate.

The comments after each call show how the handle’s type changes after every transition.

// SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

#[allow(unused)]
mod instrumentation {
    include!(concat!(env!("OUT_DIR"), "/finite_state_machine.rs"));
}

use instrumentation::{Context, FiniteStateMachine, Job, Noop};

#[rustfmt::skip]
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let context = Context::<FiniteStateMachine>::try_new(Noop)?;
    let _job = context
        .observer::<Job>()
        .handle()         // FsmHandle<Job>
        .queued()         // FsmHandle<Job, job_state::Queued>
        .loading_input()  // FsmHandle<Job, job_state::LoadingInput>
        .running()        // FsmHandle<Job, job_state::Running>
        .completed();     // FsmHandle<Job, job_state::Completed>

    Ok(())
}
Key point

The generated handle exposes only the transitions allowed from its current state.

Check yourself

Which property does the parser validate for this FSM?

Which states can directly precede running?