SESSION-02: one agent process per fly and one environment process under the coordinator over the Unix-socket transport, compared against the in-process composition and a dedicated-thread variant. The mode is the only thing that changes; the composition, the coordinator, the workers and the router are the same code in all three. The launcher is the configured supervisor. It owns a total thread budget with one allocation per participant, refused as BUSY before anything starts when the total cannot cover it; the configured client, service, worker and port identities, proved in Worker.Hello before the coordinator pins a registration; Worker.Status health on the supervisor's own monotonic clock at the ipc-v1 section 6 budgets; and reaping, where Worker.Shutdown is the request and the operating system is the guarantee. The worker executable is a subcommand of this crate's one binary, which is what implementation.md section 2 allows in place of a separate worker crate. The coordinator's fault behaviour: every failure names the participant it is attributed to, every domain call has a caller-side deadline so a dead participant is a diagnosed outcome rather than a hang, and failing fences the epoch -- the boundary stops, the handles drop, and no further transition or publication is allowed. Agent.Initialize now carries the launcher's allocation, and an agent refuses one asking for more. tests/processes.rs proves every acceptance bullet once per execution mode, and the two section 4 rows SESSION-01 could not reach in one process: a router restart during a world advance, and an old worker's reply after a restart. measure compares the three modes at one, two and four agents; its table is in the crate README, and it is not a capacity claim.
75 lines
2.8 KiB
Rust
75 lines
2.8 KiB
Rust
//! The same synthetic session in all three execution modes, printing the one behaviour trace
|
|
//! they agree on.
|
|
//!
|
|
//! ```sh
|
|
//! cargo run -p fly-session --example processes
|
|
//! ```
|
|
//!
|
|
//! The separate-process run starts one agent process per fly and one environment process
|
|
//! through this crate's own binary, so it needs that binary built:
|
|
//!
|
|
//! ```sh
|
|
//! cargo build -p fly-session --bin fly-session
|
|
//! ```
|
|
|
|
use fly_session::harness::{ExecutionMode, HarnessConfig, SessionHarness, Via};
|
|
use fly_session::launcher::default_worker_program;
|
|
|
|
#[tokio::main(flavor = "multi_thread", worker_threads = 4)]
|
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let program = default_worker_program();
|
|
println!("worker program: {}", program.display());
|
|
let mut agreed: Option<Vec<String>> = None;
|
|
|
|
for mode in ExecutionMode::all() {
|
|
let dir = tempfile::tempdir()?;
|
|
let config = HarnessConfig { mode, ..HarnessConfig::default() };
|
|
println!(
|
|
"\n=== {} : {} threads for {} participants plus the coordinator",
|
|
mode.label(),
|
|
config.budget()?.total(),
|
|
config.agents.len() + 1
|
|
);
|
|
let mut harness = SessionHarness::start(Via::Unix, dir.path(), config).await?;
|
|
harness.coordinator.bootstrap().await?;
|
|
let reports = harness.coordinator.run(3).await?;
|
|
for report in &reports {
|
|
println!(" committed boundary {}", report.boundary);
|
|
}
|
|
for (worker_id, status) in harness.launcher.health_check_all().await {
|
|
match status {
|
|
Ok(status) => println!(
|
|
" {worker_id}: {:?}, progress {}",
|
|
status.state, status.progress_counter
|
|
),
|
|
Err(e) => println!(" {worker_id}: unhealthy: {e}"),
|
|
}
|
|
}
|
|
let behaviour = harness.coordinator.trace.behavior();
|
|
match &agreed {
|
|
None => {
|
|
println!(" behaviour trace, {} transitions:", behaviour.len());
|
|
for line in &behaviour {
|
|
println!(" {line}");
|
|
}
|
|
agreed = Some(behaviour);
|
|
}
|
|
Some(first) => {
|
|
assert_eq!(
|
|
&behaviour, first,
|
|
"{} produced a different behaviour trace",
|
|
mode.label()
|
|
);
|
|
println!(" behaviour trace: identical to the first run");
|
|
}
|
|
}
|
|
let reaped = harness.launcher.reap_all("example").await;
|
|
for (worker_id, outcome) in reaped {
|
|
println!(" reaped {worker_id}: {outcome:?}");
|
|
}
|
|
harness.shutdown().await;
|
|
drop(dir);
|
|
}
|
|
println!("\nall three execution modes produced one behaviour trace");
|
|
Ok(())
|
|
}
|