byteflow-actors 0.9.3

Embeddable flow runtime: M:N scheduler, Atomic Hop (Message+Cap), supervisor — use byteflow::
Documentation
//! Atomic Hop: one [`byteflow::Value::Message`] per request/reply hop.
//!
//! Canonical Atomic Hop demo: server loop + two `Ask` clients
//! (`samples::atomic_actors`). Minted `request_id`s, stable `reply_cap`,
//! and a 72-sum join. See `docs/atomic-hop.md`.
//!
//! ```text
//! cargo run -p byteflow-actors --example atomic_actors
//!
//! # scheduler stderr (spawn/send/recv/finish) — separate from print's stdout
//! $env:BYTEFLOW_LOG="info"
//! cargo run -p byteflow-actors --example atomic_actors
//! ```
//!
//! Failures from `Runtime::…` / `spawn` are printed and exit non-zero —
//! matching the fail-closed host API (no `.expect` on the happy path).

use byteflow::{samples, std_native_table, FlowOutcome, Runtime, RuntimeConfig, Value};

fn main() {
    let chunk = samples::atomic_actors();
    let rt = match Runtime::with_natives_and_config(
        chunk,
        std_native_table(),
        RuntimeConfig {
            workers: 2,
            quantum: 10_000,
            mailbox: byteflow::MailboxConfig::DEFAULT,
            ..Default::default()
        },
    ) {
        Ok(rt) => rt,
        Err(e) => {
            eprintln!("runtime: {e}");
            std::process::exit(1);
        }
    };
    let Some(main) = rt.function_index("main") else {
        eprintln!("missing main");
        std::process::exit(1);
    };
    let handle = match rt.spawn(main, &[]) {
        Ok(h) => h,
        Err(e) => {
            eprintln!("spawn: {e}");
            std::process::exit(1);
        }
    };
    let outcome = handle.join();
    let metrics = rt.metrics();
    rt.shutdown();

    match outcome {
        FlowOutcome::Completed(Value::Int(72)) => {
            println!("atomic actors ok: two clients × 8 Ask = 72");
            println!("{metrics}");
        }
        other => {
            eprintln!("unexpected {other:?}");
            std::process::exit(1);
        }
    }
}