refactor: consolidate crates #39
58 changed files with 89 additions and 241 deletions
40
Cargo.lock
generated
40
Cargo.lock
generated
|
|
@ -1668,17 +1668,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "node"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"ctrlc",
|
||||
"distribution",
|
||||
"runtime-dashboard",
|
||||
"swactor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.50.3"
|
||||
|
|
@ -2294,6 +2283,7 @@ dependencies = [
|
|||
name = "runtime-dashboard"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"crossbeam-queue",
|
||||
"crossterm",
|
||||
"ctrlc",
|
||||
|
|
@ -2302,7 +2292,6 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"swactor",
|
||||
"swactor-command",
|
||||
"tiny_http",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
|
|
@ -2610,15 +2599,6 @@ dependencies = [
|
|||
"serde_json",
|
||||
"simulation",
|
||||
"swactor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simulation-dashboard"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simulation",
|
||||
"tiny_http",
|
||||
"toml",
|
||||
]
|
||||
|
|
@ -2727,12 +2707,14 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "swactor-command"
|
||||
name = "swactor-bin-runner"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"proptest",
|
||||
"swactor",
|
||||
"swactor-std",
|
||||
"wasmtime",
|
||||
"wat",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2743,16 +2725,6 @@ dependencies = [
|
|||
"swactor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swactor-wasm-actor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proptest",
|
||||
"swactor",
|
||||
"wasmtime",
|
||||
"wat",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.115"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
members = [".", "crates/python", "crates/wasm", "crates/wasm-actor", "crates/simulation", "crates/runtime-dashboard", "crates/distribution", "crates/simulation-dashboard", "crates/std", "crates/command", "crates/node", "tests/docker"]
|
||||
members = [".", "crates/python", "crates/wasm", "crates/bin-runner", "crates/simulation", "crates/runtime-dashboard", "crates/distribution", "crates/std", "tests/docker"]
|
||||
exclude = ["tools/depgraph"]
|
||||
|
||||
[package]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
FROM rust:1.93-slim AS builder
|
||||
WORKDIR /build
|
||||
COPY . .
|
||||
RUN cargo build --release -p node
|
||||
RUN cargo build --release -p runtime-dashboard --features node
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
COPY --from=builder /build/target/release/swactor-node /usr/local/bin/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "swactor-wasm-actor"
|
||||
name = "swactor-bin-runner"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
|
|
@ -9,5 +9,6 @@ wasmtime = "29"
|
|||
|
||||
[dev-dependencies]
|
||||
swactor = { path = "../..", features = ["getrandom"] }
|
||||
swactor-std = { path = "../std" }
|
||||
wat = "1"
|
||||
proptest = "1"
|
||||
8
crates/bin-runner/tests/wasm_actor.proptest-regressions
Normal file
8
crates/bin-runner/tests/wasm_actor.proptest-regressions
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Seeds for failure cases proptest has generated in the past. It is
|
||||
# automatically read and these particular cases re-run before any
|
||||
# novel cases are generated.
|
||||
#
|
||||
# It is recommended to check this file in to source control so that
|
||||
# everyone who runs the test benefits from these saved cases.
|
||||
cc f8674b306ba8187ad75bcc5a33c4a679e497a0053dc6fdb2234ccaeaae8f85b7 # shrinks to guest_idx = 0, n_msgs = 0, ticks_before = 1, ticks_after = 1
|
||||
cc db98a9c0726c0477ba56ec6098a1f21518faaff4551d90e915790ce3c890dd53 # shrinks to payload = []
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
use swactor::actor::{ActorAddress, ActorInterface};
|
||||
use swactor::runtime::{Ctx, Runtime, RuntimeConfig};
|
||||
use swactor_wasm_actor::{ByteMessage, SharedEngine, WasmActor, WasmActorBuilder, WasmActorError};
|
||||
use swactor_bin_runner::{ByteMessage, SharedEngine, WasmActor, WasmActorBuilder, WasmActorError};
|
||||
use swactor_std::CtxWatching;
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
[package]
|
||||
name = "swactor-command"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
swactor = { path = "../..", features = ["serde"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
[package]
|
||||
name = "node"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[[bin]]
|
||||
name = "swactor-node"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
swactor = { path = "../..", features = ["serde", "tracing", "transport"] }
|
||||
distribution = { path = "../distribution" }
|
||||
runtime-dashboard = { path = "../runtime-dashboard", features = ["distribution"] }
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
ctrlc = "3"
|
||||
|
|
@ -14,17 +14,21 @@ crossbeam-queue = "0.3.12"
|
|||
ratatui = { version = "0.29", optional = true, default-features = false, features = ["crossterm"] }
|
||||
crossterm = { version = "0.28", optional = true }
|
||||
distribution = { path = "../distribution", optional = true }
|
||||
swactor-command = { path = "../command" }
|
||||
|
||||
[dependencies.ctrlc]
|
||||
version = "3"
|
||||
clap = { version = "4", features = ["derive"], optional = true }
|
||||
ctrlc = "3"
|
||||
|
||||
[features]
|
||||
default = ["distribution"]
|
||||
tui = ["dep:ratatui", "dep:crossterm"]
|
||||
distribution = ["dep:distribution"]
|
||||
node = ["distribution", "dep:clap", "swactor/transport"]
|
||||
|
||||
[[bin]]
|
||||
name = "swactor-tui"
|
||||
path = "src/bin/tui.rs"
|
||||
required-features = ["tui"]
|
||||
|
||||
[[bin]]
|
||||
name = "swactor-node"
|
||||
path = "src/bin/swactor-node.rs"
|
||||
required-features = ["node"]
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ fn main() {
|
|||
swim: swim_config,
|
||||
cache_capacity: 1000,
|
||||
republish_interval: 500,
|
||||
..Default::default()
|
||||
};
|
||||
let mut driver = NodeDriver::new(node_config).expect("failed to create node driver");
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ impl StatsCollector {
|
|||
}
|
||||
}
|
||||
|
||||
impl swactor_command::StatsEnricher for StatsCollector {
|
||||
impl crate::command::StatsEnricher for StatsCollector {
|
||||
fn enrich(&self, stats: &mut swactor::stats::RuntimeStats) {
|
||||
stats.actor_details = self.actor_details();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use std::time::{Duration, Instant};
|
|||
use swactor::actor::ActorAddress;
|
||||
use swactor::stats::TickTiming;
|
||||
|
||||
use crate::{CommandContext, CommandHandler, CommandMeta, CommandResponse};
|
||||
use super::{CommandContext, CommandHandler, CommandMeta, CommandResponse};
|
||||
|
||||
// ─── Arg helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::CommandRequest;
|
||||
use super::CommandRequest;
|
||||
|
||||
/// Parse a REPL text line into a [`CommandRequest`].
|
||||
///
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
//! Line-oriented diagnostic protocol for LLM-driven runtime investigation.
|
||||
//!
|
||||
//! Delegates all command logic to the `swactor-command` crate.
|
||||
//! Delegates all command logic to the `command` module.
|
||||
//!
|
||||
//! Send text commands on stdin, receive JSON responses on stdout (one per line).
|
||||
//! All human-readable diagnostics go to stderr.
|
||||
|
|
@ -23,7 +23,7 @@ use std::io::{self, BufRead, Write};
|
|||
use std::sync::Arc;
|
||||
|
||||
use swactor::runtime::Runtime;
|
||||
use swactor_command::{CommandContext, CommandRouter};
|
||||
use crate::command::{CommandContext, CommandRouter};
|
||||
|
||||
use crate::collector::StatsCollector;
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ pub fn run_investigate(runtime: Arc<Runtime>, collector: Arc<StatsCollector>) ->
|
|||
break;
|
||||
}
|
||||
|
||||
let req = swactor_command::parse_line(line);
|
||||
let req = crate::command::parse_line(line);
|
||||
let resp = router.dispatch(&req, &ctx);
|
||||
|
||||
stdout.write_all(resp.to_json_line().as_bytes())?;
|
||||
|
|
@ -66,6 +66,6 @@ pub fn dispatch_command(
|
|||
router: &CommandRouter,
|
||||
ctx: &CommandContext,
|
||||
) -> String {
|
||||
let req = swactor_command::from_query_params(params);
|
||||
let req = crate::command::from_query_params(params);
|
||||
router.dispatch(&req, ctx).to_json_line()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
pub mod collector;
|
||||
pub mod command;
|
||||
pub mod history;
|
||||
pub mod investigate;
|
||||
pub mod layer;
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ pub(crate) fn spawn_http_server(
|
|||
let addr = format!("0.0.0.0:{port}");
|
||||
let server = tiny_http::Server::http(&addr).expect("failed to bind HTTP server");
|
||||
let server = Arc::new(server);
|
||||
let cmd_router = Arc::new(swactor_command::CommandRouter::with_builtins());
|
||||
let cmd_router = Arc::new(crate::command::CommandRouter::with_builtins());
|
||||
|
||||
for _ in 0..4 {
|
||||
let server = Arc::clone(&server);
|
||||
|
|
@ -362,7 +362,7 @@ fn handle_investigate_api(
|
|||
url: &str,
|
||||
runtime: Arc<Mutex<Option<Arc<Runtime>>>>,
|
||||
collector: Arc<Mutex<Option<Arc<StatsCollector>>>>,
|
||||
cmd_router: Arc<swactor_command::CommandRouter>,
|
||||
cmd_router: Arc<crate::command::CommandRouter>,
|
||||
) {
|
||||
let params = parse_query_string(url);
|
||||
|
||||
|
|
@ -371,13 +371,13 @@ fn handle_investigate_api(
|
|||
|
||||
let json = match (maybe_rt, maybe_col) {
|
||||
(Some(rt), Some(col)) => {
|
||||
let ctx = swactor_command::CommandContext::with_enricher(rt, col);
|
||||
let req = swactor_command::from_query_params(¶ms);
|
||||
let ctx = crate::command::CommandContext::with_enricher(rt, col);
|
||||
let req = crate::command::from_query_params(¶ms);
|
||||
cmd_router.dispatch(&req, &ctx).to_json_line()
|
||||
}
|
||||
(Some(rt), None) => {
|
||||
let ctx = swactor_command::CommandContext::new(rt);
|
||||
let req = swactor_command::from_query_params(¶ms);
|
||||
let ctx = crate::command::CommandContext::new(rt);
|
||||
let req = crate::command::from_query_params(¶ms);
|
||||
cmd_router.dispatch(&req, &ctx).to_json_line()
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use std::sync::Arc;
|
|||
|
||||
use swactor::actor::ActorInterface;
|
||||
use swactor::runtime::{Ctx, Runtime, RuntimeConfig};
|
||||
use swactor_command::{
|
||||
use runtime_dashboard::command::{
|
||||
from_query_params, parse_line, CommandContext, CommandRequest, CommandResponse, CommandRouter,
|
||||
};
|
||||
|
||||
|
|
@ -310,9 +310,9 @@ fn from_query_params_defaults_to_help() {
|
|||
#[test]
|
||||
fn custom_command_handler() {
|
||||
struct PingCommand;
|
||||
impl swactor_command::CommandHandler for PingCommand {
|
||||
fn meta(&self) -> swactor_command::CommandMeta {
|
||||
swactor_command::CommandMeta {
|
||||
impl runtime_dashboard::command::CommandHandler for PingCommand {
|
||||
fn meta(&self) -> runtime_dashboard::command::CommandMeta {
|
||||
runtime_dashboard::command::CommandMeta {
|
||||
name: "ping",
|
||||
description: "Respond with pong",
|
||||
usage: "ping",
|
||||
|
|
@ -13,6 +13,7 @@ fn make_event(message: &str) -> DashboardEvent {
|
|||
level: "INFO".into(),
|
||||
message: message.into(),
|
||||
worker_id: None,
|
||||
actor_addr: None,
|
||||
fields: serde_json::Map::new(),
|
||||
}
|
||||
}
|
||||
|
|
@ -181,6 +182,7 @@ fn three_workers_report_independently_merged_view_is_complete() {
|
|||
last_msg_type: Some("Ping"),
|
||||
messages_processed: 100,
|
||||
poisoned: false,
|
||||
message_type_counts: vec![],
|
||||
}]);
|
||||
|
||||
// Worker 1 reports 1 actor
|
||||
|
|
@ -190,6 +192,7 @@ fn three_workers_report_independently_merged_view_is_complete() {
|
|||
last_msg_type: None,
|
||||
messages_processed: 50,
|
||||
poisoned: false,
|
||||
message_type_counts: vec![],
|
||||
}]);
|
||||
|
||||
// Worker 2 reports 1 actor (poisoned)
|
||||
|
|
@ -199,6 +202,7 @@ fn three_workers_report_independently_merged_view_is_complete() {
|
|||
last_msg_type: Some("BadMsg"),
|
||||
messages_processed: 10,
|
||||
poisoned: true,
|
||||
message_type_counts: vec![],
|
||||
}]);
|
||||
|
||||
// Dashboard reads merged view
|
||||
|
|
@ -228,6 +232,7 @@ fn worker_update_replaces_stale_snapshot() {
|
|||
last_msg_type: None,
|
||||
messages_processed: 10,
|
||||
poisoned: false,
|
||||
message_type_counts: vec![],
|
||||
}]);
|
||||
|
||||
assert_eq!(collector.actor_details().len(), 1);
|
||||
|
|
@ -240,6 +245,7 @@ fn worker_update_replaces_stale_snapshot() {
|
|||
last_msg_type: Some("Update"),
|
||||
messages_processed: 25,
|
||||
poisoned: false,
|
||||
message_type_counts: vec![],
|
||||
}]);
|
||||
|
||||
let details = collector.actor_details();
|
||||
|
|
@ -261,6 +267,7 @@ fn worker_reports_empty_after_all_actors_stop() {
|
|||
last_msg_type: None,
|
||||
messages_processed: 5,
|
||||
poisoned: false,
|
||||
message_type_counts: vec![],
|
||||
}]);
|
||||
assert_eq!(collector.actor_details().len(), 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
[package]
|
||||
name = "simulation-dashboard"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
simulation = { path = "../simulation", features = ["gossip"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
tiny_http = "0.12"
|
||||
toml = "0.8"
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
# gossip-dashboard
|
||||
|
||||
Interactive web dashboard for visualizing gossip protocol simulations.
|
||||
|
||||
The workflow has two steps:
|
||||
|
||||
1. **Generate traces** -- run simulations against TOML config files, producing `.trace.json` files.
|
||||
2. **Replay traces** -- start the dashboard server, point it at a directory of traces, and explore them in the browser.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
# 1. Generate traces from the bundled configs (outputs to traces/)
|
||||
cargo run -p gossip-dashboard --example generate_traces
|
||||
|
||||
# 2. Launch the dashboard
|
||||
cargo run -p gossip-dashboard --example replay -- traces
|
||||
# => open http://localhost:8080
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
### `generate_traces`
|
||||
|
||||
Runs gossip simulations and writes `.trace.json` files.
|
||||
|
||||
```
|
||||
generate_traces # all bundled configs -> traces/
|
||||
generate_traces <out-dir> # all bundled configs -> <out-dir>/
|
||||
generate_traces <out-dir> <config.toml> [more.toml …] # specific configs -> <out-dir>/
|
||||
```
|
||||
|
||||
Bundled configs live in `examples/configs/`. When no config paths are given, every `.toml` in that directory is run.
|
||||
|
||||
Output filenames are derived from the simulation name (lowercased, spaces to underscores). Example output:
|
||||
|
||||
```
|
||||
traces/
|
||||
ring_10_nodes.trace.json
|
||||
star_7_nodes.trace.json
|
||||
chain_8_nodes.trace.json
|
||||
full_mesh_6_nodes.trace.json
|
||||
partition_&_heal_8_nodes.trace.json
|
||||
```
|
||||
|
||||
### `replay`
|
||||
|
||||
Starts an HTTP server that serves the dashboard UI and the trace data.
|
||||
|
||||
```
|
||||
replay <trace-dir> [port]
|
||||
```
|
||||
|
||||
| Argument | Required | Default | Description |
|
||||
|-------------|----------|---------|------------------------------------------|
|
||||
| `trace-dir` | yes | -- | Directory containing `.trace.json` files |
|
||||
| `port` | no | 8080 | Port to bind on |
|
||||
|
||||
The server exposes three endpoints:
|
||||
|
||||
| Route | Description |
|
||||
|--------------------------|------------------------------------|
|
||||
| `GET /` | Dashboard HTML |
|
||||
| `GET /traces` | JSON list of available trace files |
|
||||
| `GET /trace.json?file=…` | Fetch a specific trace |
|
||||
|
||||
## Configuration (TOML)
|
||||
|
||||
Each simulation is defined by a TOML file. Example (`ring_10.toml`):
|
||||
|
||||
```toml
|
||||
name = "Ring (10 nodes)"
|
||||
topology = "ring"
|
||||
num_nodes = 10
|
||||
num_rounds = 15
|
||||
ticks_per_round = 5
|
||||
num_threads = 1
|
||||
|
||||
[initial_data]
|
||||
color = "blue"
|
||||
version = "1"
|
||||
status = "active"
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|--------------------|-------------------|----------|-------------------------------------------------------------------|
|
||||
| `name` | string | yes | Display name for the simulation |
|
||||
| `topology` | string | yes | Network topology (see below) |
|
||||
| `num_nodes` | integer | yes | Number of gossip nodes |
|
||||
| `num_rounds` | integer | yes | Number of gossip rounds to run |
|
||||
| `ticks_per_round` | integer | yes | Simulation ticks per round |
|
||||
| `num_threads` | integer | yes | Worker threads (`1` = deterministic single-threaded) |
|
||||
| `heal_after_round` | integer | no | Round after which partitioned halves are bridged |
|
||||
| `initial_data` | table of strings | no | Key-value pairs seeded on node 0 before gossip begins |
|
||||
|
||||
### Topologies
|
||||
|
||||
| Value | Shape |
|
||||
|---------------|--------------------------------------------------------------------------|
|
||||
| `ring` | Each node connects to the next, forming a circle |
|
||||
| `star` | Node 0 is a hub with bidirectional links to every other node |
|
||||
| `full_mesh` | Every node connects bidirectionally to every other node |
|
||||
| `chain` | Unidirectional chain: node 0 -> 1 -> 2 -> ... -> N-1 |
|
||||
| `partitioned` | Two isolated full-mesh halves; use `heal_after_round` to bridge them |
|
||||
|
||||
## Bundled configs
|
||||
|
||||
| File | Topology | Nodes | Rounds | Notes |
|
||||
|---------------------------|-------------|-------|--------|----------------------------|
|
||||
| `ring_10.toml` | ring | 10 | 15 | |
|
||||
| `star_7.toml` | star | 7 | 10 | |
|
||||
| `full_mesh_6.toml` | full_mesh | 6 | 8 | |
|
||||
| `chain_8.toml` | chain | 8 | 20 | |
|
||||
| `partitioned_8_heal.toml` | partitioned | 8 | 20 | Heals after round 10 |
|
||||
|
||||
## Dashboard UI
|
||||
|
||||
Once a trace is loaded in the browser:
|
||||
|
||||
- **Graph canvas** -- nodes arranged in a circle then refined with force-directed layout. Nodes and edges flash as events are replayed.
|
||||
- **Stats panel** -- total nodes, edges, messages, current round.
|
||||
- **Worker logs** -- per-thread activity feed.
|
||||
- **Event table** -- full event log with columns: Seq, Round, Thread, Node, Event, Details.
|
||||
- **Playback controls** -- First / Prev / Play / Pause / Next / Last, timeline slider, speed adjustment (10 ms -- 2000 ms per event).
|
||||
|
|
@ -6,6 +6,7 @@ edition = "2024"
|
|||
[features]
|
||||
default = []
|
||||
gossip = ["dep:log"]
|
||||
dashboard = ["gossip", "dep:tiny_http", "dep:toml"]
|
||||
|
||||
[dependencies]
|
||||
distribution = { path = "../distribution" }
|
||||
|
|
@ -14,6 +15,8 @@ serde = { version = "1", features = ["derive"] }
|
|||
serde_json = "1"
|
||||
getrandom = "0.2"
|
||||
log = { version = "0.4", optional = true }
|
||||
tiny_http = { version = "0.12", optional = true }
|
||||
toml = { version = "0.8", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
simulation = { path = ".", features = ["gossip"] }
|
||||
|
|
@ -21,3 +24,11 @@ simulation = { path = ".", features = ["gossip"] }
|
|||
[[example]]
|
||||
name = "gossip_sim"
|
||||
required-features = ["gossip"]
|
||||
|
||||
[[example]]
|
||||
name = "replay"
|
||||
required-features = ["dashboard"]
|
||||
|
||||
[[example]]
|
||||
name = "generate_traces"
|
||||
required-features = ["dashboard"]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use simulation_dashboard::config::SimFileConfig;
|
||||
use simulation_dashboard::save_trace;
|
||||
use simulation::dashboard::config::SimFileConfig;
|
||||
use simulation::dashboard::save_trace;
|
||||
use simulation::gossip::sim::run_simulation;
|
||||
|
||||
const CONFIGS_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/examples/configs");
|
||||
|
|
@ -54,7 +54,7 @@ fn main() {
|
|||
trace.events.len()
|
||||
);
|
||||
}
|
||||
eprintln!("Done. View with: cargo run -p simulation-dashboard --example replay -- {out_dir}");
|
||||
eprintln!("Done. View with: cargo run -p simulation --features dashboard --example replay -- {out_dir}");
|
||||
}
|
||||
|
||||
fn collect_configs(dir: &str) -> Vec<PathBuf> {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use simulation_dashboard::serve_dashboard;
|
||||
use simulation::dashboard::serve_dashboard;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
|
@ -3,8 +3,8 @@ use std::fs;
|
|||
use std::io;
|
||||
|
||||
use serde::Deserialize;
|
||||
use simulation::gossip::sim::GossipSimConfig;
|
||||
use simulation::topology::Topology;
|
||||
use crate::gossip::sim::GossipSimConfig;
|
||||
use crate::topology::Topology;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SimFileConfig {
|
||||
|
|
@ -7,7 +7,7 @@ pub use server::serve_dashboard;
|
|||
use std::fs;
|
||||
use std::io;
|
||||
|
||||
use simulation::gossip::trace::SimulationTrace;
|
||||
use crate::gossip::trace::SimulationTrace;
|
||||
|
||||
pub fn save_trace(trace: &SimulationTrace, path: &str) -> io::Result<()> {
|
||||
let json = serde_json::to_string_pretty(trace)
|
||||
|
|
@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::dashboard_html::DASHBOARD_HTML;
|
||||
use super::dashboard_html::DASHBOARD_HTML;
|
||||
|
||||
// ── Trace directory scanning ──────────────────────────────────────────
|
||||
|
||||
|
|
@ -6,3 +6,6 @@ pub mod distribution;
|
|||
|
||||
#[cfg(feature = "gossip")]
|
||||
pub mod gossip;
|
||||
|
||||
#[cfg(feature = "dashboard")]
|
||||
pub mod dashboard;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use wasm_bindgen::prelude::*;
|
|||
|
||||
use swactor::actor::{ActorAddress, ActorExited, ActorInterface};
|
||||
use swactor::runtime::{Ctx, Inbox, Runtime, RuntimeConfig};
|
||||
use swactor_std::{CtxGroups, RuntimeNaming, RuntimeGroups, StdExtension};
|
||||
use swactor_std::{CtxGroups, CtxWatching, RuntimeNaming, RuntimeGroups, StdExtension};
|
||||
|
||||
// ─── Core JS-facing types ───────────────────────────────────────────────────
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Wasm Actor Crate — Development History
|
||||
|
||||
> Adds a new crate (`crates/wasm-actor/`) that runs WebAssembly guest code
|
||||
> Adds a new crate (`crates/bin-runner/`) that runs WebAssembly guest code
|
||||
> **inside** a swactor actor. The Wasm instance lives in the actor — not as a
|
||||
> separate OS process. Messages arrive as bytes, get written into Wasm linear
|
||||
> memory, and the guest's `handle` export is called.
|
||||
|
|
@ -30,7 +30,7 @@ Swactor already supported running *inside* a browser via `crates/wasm/`
|
|||
plugins, multi-language actors, and capability-restricted compute.
|
||||
|
||||
The main swactor crate has no wasmtime dependency — all Wasm machinery is
|
||||
isolated in `crates/wasm-actor/`.
|
||||
isolated in `crates/bin-runner/`.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -38,14 +38,14 @@ isolated in `crates/wasm-actor/`.
|
|||
|
||||
| Component | Location | Purpose |
|
||||
|-----------|----------|---------|
|
||||
| `swactor-wasm-actor` crate | `crates/wasm-actor/` | Host-side: engine, builder, actor impl |
|
||||
| 3 guest crates | `crates/wasm-actor/tests/guests/{echo,double,silent}/` | `#![no_std]` Wasm modules for testing |
|
||||
| Integration tests | `crates/wasm-actor/tests/wasm_actor.rs` | 7 behavioral tests |
|
||||
| `swactor-bin-runner` crate | `crates/bin-runner/` | Host-side: engine, builder, actor impl |
|
||||
| 3 guest crates | `crates/bin-runner/tests/guests/{echo,double,silent}/` | `#![no_std]` Wasm modules for testing |
|
||||
| Integration tests | `crates/bin-runner/tests/wasm_actor.rs` | 7 behavioral tests |
|
||||
|
||||
### Crate modules
|
||||
|
||||
```
|
||||
crates/wasm-actor/src/
|
||||
crates/bin-runner/src/
|
||||
lib.rs — ByteMessage, re-exports
|
||||
engine.rs — SharedEngine (Arc<wasmtime::Engine>)
|
||||
builder.rs — WasmActorBuilder (compile + link + instantiate)
|
||||
|
|
@ -138,9 +138,9 @@ This allows guests to send replies without hardcoding addresses.
|
|||
```bash
|
||||
rustup target add wasm32-unknown-unknown # one-time
|
||||
|
||||
cd crates/wasm-actor/tests/guests/echo && cargo build --target wasm32-unknown-unknown --release
|
||||
cd crates/wasm-actor/tests/guests/double && cargo build --target wasm32-unknown-unknown --release
|
||||
cd crates/wasm-actor/tests/guests/silent && cargo build --target wasm32-unknown-unknown --release
|
||||
cd crates/bin-runner/tests/guests/echo && cargo build --target wasm32-unknown-unknown --release
|
||||
cd crates/bin-runner/tests/guests/double && cargo build --target wasm32-unknown-unknown --release
|
||||
cd crates/bin-runner/tests/guests/silent && cargo build --target wasm32-unknown-unknown --release
|
||||
```
|
||||
|
||||
Each guest crate has its own `[workspace]` marker to stay independent of the
|
||||
|
|
@ -178,7 +178,7 @@ root workspace.
|
|||
|
||||
## 8. Test Coverage Summary
|
||||
|
||||
7 behavioral tests in `crates/wasm-actor/tests/wasm_actor.rs`:
|
||||
7 behavioral tests in `crates/bin-runner/tests/wasm_actor.rs`:
|
||||
|
||||
| Test | Scenario |
|
||||
|------|----------|
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ dependencies = [
|
|||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
swactor = { path = "../python", editable = true }
|
||||
swactor = { path = "../../crates/python", editable = true }
|
||||
|
||||
[[tool.uv.index]]
|
||||
name = "pytorch-cpu"
|
||||
|
|
@ -16,4 +16,4 @@ SWACTOR_TRACE_DIR="$DIR" cargo test -p simulation \
|
|||
COUNT=$(find "$DIR" -name '*.trace.json' 2>/dev/null | wc -l)
|
||||
echo "$COUNT traces in $DIR/"
|
||||
echo "Dashboard at http://localhost:$PORT"
|
||||
cargo run -p simulation-dashboard --example replay -- "$DIR" "$PORT"
|
||||
cargo run -p simulation --features dashboard --example replay -- "$DIR" "$PORT"
|
||||
|
|
|
|||
Loading…
Reference in a new issue