diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..17eb168
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,2 @@
+*
+!target/x86_64-unknown-linux-musl/release/swactor
diff --git a/.gitignore b/.gitignore
index ffbe531..255f80e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,11 @@ docs/architecture.html
crates/simulation/traces
# xtask personal config
-xtask/config.toml
\ No newline at end of file
+xtask/config.toml
+
+# Deploy config (machine-specific)
+deploy.toml
+.deploy/
+
+# Local dev node state
+.dev-node/
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index a1351a9..e00b73d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -287,6 +287,58 @@ dependencies = [
"fs_extra",
]
+[[package]]
+name = "axum"
+version = "0.8.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
+dependencies = [
+ "axum-core",
+ "bytes",
+ "form_urlencoded",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde_core",
+ "serde_json",
+ "serde_path_to_error",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "tokio",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http",
+ "http-body",
+ "http-body-util",
+ "mime",
+ "pin-project-lite",
+ "sync_wrapper",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
[[package]]
name = "backon"
version = "1.6.0"
@@ -337,12 +389,6 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
[[package]]
name = "bitflags"
version = "2.11.0"
@@ -489,21 +535,6 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901"
-[[package]]
-name = "ci-relay"
-version = "0.1.0"
-dependencies = [
- "clap",
- "hex",
- "hmac",
- "iroh",
- "serde_json",
- "sha2 0.10.9",
- "swactor-ci",
- "tiny_http",
- "tokio",
-]
-
[[package]]
name = "ciborium"
version = "0.2.2"
@@ -619,15 +650,6 @@ dependencies = [
"static_assertions",
]
-[[package]]
-name = "concurrent-queue"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
-dependencies = [
- "crossbeam-utils",
-]
-
[[package]]
name = "const-oid"
version = "0.9.6"
@@ -916,7 +938,7 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"crossterm_winapi",
"mio",
"parking_lot",
@@ -1085,6 +1107,28 @@ dependencies = [
"syn",
]
+[[package]]
+name = "dashboard"
+version = "0.1.0"
+dependencies = [
+ "axum",
+ "clap",
+ "crossbeam-queue",
+ "crossterm",
+ "ctrlc",
+ "distribution",
+ "iroh",
+ "ratatui",
+ "serde",
+ "serde_json",
+ "swactor",
+ "swactor-std",
+ "tokio",
+ "tokio-stream",
+ "tracing",
+ "tracing-subscriber",
+]
+
[[package]]
name = "dashmap"
version = "6.1.0"
@@ -1267,7 +1311,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"block2",
"libc",
"objc2",
@@ -1512,17 +1556,6 @@ dependencies = [
"miniz_oxide",
]
-[[package]]
-name = "flume"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
-dependencies = [
- "futures-core",
- "futures-sink",
- "spin 0.9.8",
-]
-
[[package]]
name = "fnv"
version = "1.0.7"
@@ -1700,7 +1733,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"debugid",
"fxhash",
"serde",
@@ -2241,16 +2274,6 @@ dependencies = [
"icu_properties",
]
-[[package]]
-name = "if-addrs"
-version = "0.13.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69b2eeee38fef3aa9b4cc5f1beea8a2444fc00e7377cafae396de3f5c2065e24"
-dependencies = [
- "libc",
- "windows-sys 0.59.0",
-]
-
[[package]]
name = "igd-next"
version = "0.16.2"
@@ -2709,7 +2732,7 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"libc",
]
@@ -2737,20 +2760,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
-[[package]]
-name = "local-runner"
-version = "0.1.0"
-dependencies = [
- "clap",
- "ctrlc",
- "iroh",
- "runtime-dashboard",
- "serde_json",
- "swactor",
- "swactor-ci",
- "tokio",
-]
-
[[package]]
name = "lock_api"
version = "0.4.14"
@@ -2828,17 +2837,10 @@ dependencies = [
]
[[package]]
-name = "mdns-sd"
-version = "0.11.5"
+name = "matchit"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fe7c11a1eb3cfbfcf702d1601c1f5f4c102cdc8665b8a557783ef634741676e"
-dependencies = [
- "flume",
- "if-addrs",
- "log",
- "polling",
- "socket2 0.5.10",
-]
+checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "memchr"
@@ -3022,7 +3024,7 @@ version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ec2f5b6839be2a19d7fa5aab5bc444380f6311c2b693551cb80f45caaa7b5ef"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"libc",
"log",
"netlink-packet-core",
@@ -3034,7 +3036,7 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"libc",
"log",
"netlink-packet-core",
@@ -3109,7 +3111,7 @@ version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"cfg-if",
"cfg_aliases",
"libc",
@@ -3229,7 +3231,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"block2",
"dispatch2",
"libc",
@@ -3248,7 +3250,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"objc2",
"objc2-core-foundation",
]
@@ -3259,7 +3261,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"dispatch2",
"libc",
"objc2",
@@ -3325,7 +3327,7 @@ version = "0.10.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"cfg-if",
"foreign-types",
"libc",
@@ -3573,22 +3575,6 @@ dependencies = [
"plotters-backend",
]
-[[package]]
-name = "polling"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
-dependencies = [
- "autocfg",
- "bitflags 1.3.2",
- "cfg-if",
- "concurrent-queue",
- "libc",
- "log",
- "pin-project-lite",
- "windows-sys 0.48.0",
-]
-
[[package]]
name = "portable-atomic"
version = "1.13.1"
@@ -3710,7 +3696,7 @@ checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532"
dependencies = [
"bit-set",
"bit-vec",
- "bitflags 2.11.0",
+ "bitflags",
"num-traits",
"rand",
"rand_chacha",
@@ -3962,7 +3948,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"cassowary",
"compact_str",
"crossterm",
@@ -4017,7 +4003,7 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
]
[[package]]
@@ -4194,26 +4180,6 @@ dependencies = [
"windows-sys 0.52.0",
]
-[[package]]
-name = "runtime-dashboard"
-version = "0.1.0"
-dependencies = [
- "clap",
- "crossbeam-queue",
- "crossterm",
- "ctrlc",
- "distribution",
- "iroh",
- "ratatui",
- "serde",
- "serde_json",
- "swactor",
- "swactor-ci",
- "tiny_http",
- "tracing",
- "tracing-subscriber",
-]
-
[[package]]
name = "rustc-demangle"
version = "0.1.27"
@@ -4250,7 +4216,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"errno",
"libc",
"linux-raw-sys 0.4.15",
@@ -4263,7 +4229,7 @@ version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"errno",
"libc",
"linux-raw-sys 0.11.0",
@@ -4441,7 +4407,7 @@ version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
@@ -4543,6 +4509,17 @@ dependencies = [
"zmij",
]
+[[package]]
+name = "serde_path_to_error"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
+dependencies = [
+ "itoa",
+ "serde",
+ "serde_core",
+]
+
[[package]]
name = "serde_spanned"
version = "0.6.9"
@@ -4712,7 +4689,7 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
]
[[package]]
@@ -4928,35 +4905,32 @@ dependencies = [
name = "swactor-ci"
version = "0.1.0"
dependencies = [
+ "clap",
+ "ctrlc",
+ "dashboard",
"hex",
"hmac",
+ "iroh",
"serde",
"serde_json",
"serde_yaml",
"sha2 0.10.9",
"swactor",
"tiny_http",
+ "tokio",
"ureq",
]
-[[package]]
-name = "swactor-crypto-wasm"
-version = "0.1.0"
-dependencies = [
- "ed25519-dalek 2.2.0",
-]
-
[[package]]
name = "swactor-datastore"
version = "0.1.0"
dependencies = [
"blake3",
"clap",
- "ctrlc",
+ "dashboard",
"distribution",
"getrandom 0.2.17",
"proptest",
- "runtime-dashboard",
"serde",
"serde_json",
"shared-types",
@@ -4964,7 +4938,6 @@ dependencies = [
"swactor-std",
"tempfile",
"tiny_http",
- "toml 0.8.23",
"ureq",
]
@@ -4974,14 +4947,14 @@ version = "0.1.0"
dependencies = [
"clap",
"ctrlc",
+ "dashboard",
"distribution",
"iroh",
"libc",
- "mdns-sd",
- "runtime-dashboard",
"serde",
"swactor",
"swactor-datastore",
+ "swactor-std",
"toml 0.8.23",
]
@@ -5030,7 +5003,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"core-foundation 0.9.4",
"system-configuration-sys",
]
@@ -5443,6 +5416,7 @@ dependencies = [
"tokio",
"tower-layer",
"tower-service",
+ "tracing",
]
[[package]]
@@ -5451,7 +5425,7 @@ version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"bytes",
"futures-util",
"http",
@@ -5797,15 +5771,6 @@ dependencies = [
"wit-bindgen",
]
-[[package]]
-name = "wasm"
-version = "0.1.0"
-dependencies = [
- "swactor",
- "swactor-std",
- "wasm-bindgen",
-]
-
[[package]]
name = "wasm-bindgen"
version = "0.2.108"
@@ -5907,6 +5872,15 @@ dependencies = [
"wasmparser 0.244.0",
]
+[[package]]
+name = "wasm-runtime"
+version = "0.1.0"
+dependencies = [
+ "swactor",
+ "swactor-std",
+ "wasm-bindgen",
+]
+
[[package]]
name = "wasm-streams"
version = "0.4.2"
@@ -5926,7 +5900,7 @@ version = "0.221.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d06bfa36ab3ac2be0dee563380147a5b81ba10dd8885d7fbbc9eb574be67d185"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"hashbrown 0.15.5",
"indexmap",
"semver",
@@ -5939,7 +5913,7 @@ version = "0.244.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"hashbrown 0.15.5",
"indexmap",
"semver",
@@ -5951,7 +5925,7 @@ version = "0.245.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e"
dependencies = [
- "bitflags 2.11.0",
+ "bitflags",
"indexmap",
"semver",
]
@@ -5976,7 +5950,7 @@ dependencies = [
"addr2line",
"anyhow",
"async-trait",
- "bitflags 2.11.0",
+ "bitflags",
"bumpalo",
"cc",
"cfg-if",
@@ -6849,7 +6823,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
dependencies = [
"anyhow",
- "bitflags 2.11.0",
+ "bitflags",
"indexmap",
"log",
"serde",
diff --git a/Cargo.toml b/Cargo.toml
index 7787d60..071ee24 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,23 +2,20 @@
members = [
".",
"crates/python",
- "crates/wasm",
+ "crates/wasm/runtime",
"crates/bin-runner",
"crates/simulation",
- "crates/runtime-dashboard",
+ "crates/dashboard",
"crates/distribution",
"crates/std",
"crates/datastore",
"crates/shared-types",
- "crates/crypto-wasm",
"crates/swactor-node",
"tests/docker",
"crates/ci",
- "crates/local-runner",
- "crates/ci-relay",
"xtask",
]
-exclude = ["tools/depgraph"]
+exclude = ["tools/depgraph", "crates/wasm/crypto"]
[package]
name = "swactor"
diff --git a/Dockerfile b/Dockerfile
index f0b6929..1e65f4a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,8 +1,3 @@
-FROM rust:1.93-slim AS builder
-WORKDIR /build
-COPY . .
-RUN cargo build --release -p swactor-node
-
-FROM debian:bookworm-slim
-COPY --from=builder /build/target/release/swactor /usr/local/bin/
-ENTRYPOINT ["swactor"]
+FROM scratch
+COPY target/x86_64-unknown-linux-musl/release/swactor /swactor
+ENTRYPOINT ["/swactor"]
diff --git a/crates/ci-relay/Cargo.toml b/crates/ci-relay/Cargo.toml
deleted file mode 100644
index 215dbcd..0000000
--- a/crates/ci-relay/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-name = "ci-relay"
-version = "0.1.0"
-edition = "2024"
-
-[[bin]]
-name = "ci-relay"
-path = "src/main.rs"
-
-[dependencies]
-swactor-ci = { path = "../ci", features = ["local"] }
-iroh = "0.96"
-tokio = { version = "1", features = ["rt-multi-thread"] }
-tiny_http = "0.12"
-serde_json = "1"
-hmac = "0.12"
-sha2 = "0.10"
-hex = "0.4"
-clap = { version = "4", features = ["derive"] }
diff --git a/crates/ci/Cargo.toml b/crates/ci/Cargo.toml
index 5a28b8e..4473d9c 100644
--- a/crates/ci/Cargo.toml
+++ b/crates/ci/Cargo.toml
@@ -9,13 +9,20 @@ serde = { version = "1", features = ["derive"] }
serde_yaml = "0.9"
serde_json = "1"
-# Local runner library dependencies
+# Shared optional deps (used by lib local feature and binaries)
tiny_http = { version = "0.12", optional = true }
ureq = { version = "2", features = ["json"], optional = true }
hmac = { version = "0.12", optional = true }
sha2 = { version = "0.10", optional = true }
hex = { version = "0.4", optional = true }
+# Binary-only optional deps
+iroh = { version = "0.96", optional = true }
+tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
+clap = { version = "4", features = ["derive"], optional = true }
+ctrlc = { version = "3", optional = true }
+dashboard = { path = "../dashboard", optional = true }
+
[features]
default = []
local = [
@@ -25,5 +32,29 @@ local = [
"dep:sha2",
"dep:hex",
]
+relay = [
+ "local",
+ "dep:iroh",
+ "dep:tokio",
+ "dep:clap",
+]
+runner = [
+ "local",
+ "dep:iroh",
+ "dep:tokio",
+ "dep:clap",
+ "dep:ctrlc",
+ "dep:dashboard",
+]
[dev-dependencies]
+
+[[bin]]
+name = "ci-relay"
+path = "src/bin/ci_relay.rs"
+required-features = ["relay"]
+
+[[bin]]
+name = "local-runner"
+path = "src/bin/local_runner.rs"
+required-features = ["runner"]
diff --git a/crates/ci-relay/src/main.rs b/crates/ci/src/bin/ci_relay.rs
similarity index 100%
rename from crates/ci-relay/src/main.rs
rename to crates/ci/src/bin/ci_relay.rs
diff --git a/crates/local-runner/src/main.rs b/crates/ci/src/bin/local_runner.rs
similarity index 91%
rename from crates/local-runner/src/main.rs
rename to crates/ci/src/bin/local_runner.rs
index 4519663..67adac4 100644
--- a/crates/local-runner/src/main.rs
+++ b/crates/ci/src/bin/local_runner.rs
@@ -14,7 +14,7 @@ use swactor::actor::ActorAddress;
use swactor::config::RuntimeConfig;
use swactor::runtime::Runtime;
-use runtime_dashboard::ci_collector::{
+use dashboard::ci_collector::{
CiSnapshot, CiStatsProvider, JobSnapshot, PipelineSnapshot, ProvisionerStatus,
};
@@ -92,22 +92,34 @@ impl CiStatsProvider for LocalCiSnapshotProvider {
}
fn pipeline_to_dashboard(p: &PipelineExecution) -> PipelineSnapshot {
+ // Convert between swactor_ci types and dashboard::ci_collector types
+ // (structurally identical but separate to avoid a dependency cycle).
+ let status: dashboard::ci_collector::PipelineStatus =
+ serde_json::from_value(serde_json::to_value(&p.status).unwrap()).unwrap();
+
PipelineSnapshot {
- pipeline_id: p.pipeline_id,
+ pipeline_id: dashboard::ci_collector::PipelineId(p.pipeline_id.0),
pipeline_name: p.pipeline_name.clone(),
repo_owner: p.repo_owner.clone(),
repo_name: p.repo_name.clone(),
commit_sha: p.commit_sha.clone(),
branch: p.branch.clone(),
- status: p.status.clone(),
+ status,
jobs: p
.jobs
.values()
- .map(|j| JobSnapshot {
- job_id: j.job_id.clone(),
- job_name: j.definition.name.clone(),
- status: j.status.clone(),
- output_line_count: j.output_lines.len(),
+ .map(|j| {
+ let job_status: dashboard::ci_collector::JobStatus =
+ serde_json::from_value(serde_json::to_value(&j.status).unwrap()).unwrap();
+ JobSnapshot {
+ job_id: dashboard::ci_collector::JobId {
+ pipeline_id: dashboard::ci_collector::PipelineId(j.job_id.pipeline_id.0),
+ job_name: j.job_id.job_name.clone(),
+ },
+ job_name: j.definition.name.clone(),
+ status: job_status,
+ output_line_count: j.output_lines.len(),
+ }
})
.collect(),
}
@@ -128,7 +140,7 @@ fn main() {
// Optionally start dashboard.
let dash = args.dashboard_port.map(|port| {
- let d = runtime_dashboard::start_dashboard(runtime_dashboard::DashboardConfig {
+ let d = dashboard::start_dashboard(dashboard::DashboardConfig {
port,
..Default::default()
});
@@ -138,7 +150,7 @@ fn main() {
// Create 2-thread runtime.
let num_threads = 2;
- let collector = runtime_dashboard::collector::StatsCollector::new(num_threads);
+ let collector = dashboard::collector::StatsCollector::new(num_threads);
let mut rt = Runtime::new(RuntimeConfig {
num_threads,
max_actors: 256,
diff --git a/crates/runtime-dashboard/.gitignore b/crates/dashboard/.gitignore
similarity index 100%
rename from crates/runtime-dashboard/.gitignore
rename to crates/dashboard/.gitignore
diff --git a/crates/runtime-dashboard/AGENTS.md b/crates/dashboard/AGENTS.md
similarity index 100%
rename from crates/runtime-dashboard/AGENTS.md
rename to crates/dashboard/AGENTS.md
diff --git a/crates/runtime-dashboard/Cargo.toml b/crates/dashboard/Cargo.toml
similarity index 84%
rename from crates/runtime-dashboard/Cargo.toml
rename to crates/dashboard/Cargo.toml
index 4556bd8..5d7fd03 100644
--- a/crates/runtime-dashboard/Cargo.toml
+++ b/crates/dashboard/Cargo.toml
@@ -1,15 +1,18 @@
[package]
-name = "runtime-dashboard"
+name = "dashboard"
version = "0.1.0"
edition = "2024"
[dependencies]
swactor = { path = "../..", features = ["serde", "tracing"] }
+swactor-std = { path = "../std", default-features = false }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["registry"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
-tiny_http = "0.12"
+axum = "0.8"
+tokio = { version = "1", features = ["net", "rt-multi-thread", "sync", "time"] }
+tokio-stream = "0.1"
crossbeam-queue = "0.3.12"
ratatui = { version = "0.29", optional = true, default-features = false, features = ["crossterm"] }
crossterm = { version = "0.28", optional = true }
@@ -17,7 +20,6 @@ distribution = { path = "../distribution", optional = true }
clap = { version = "4", features = ["derive"], optional = true }
ctrlc = "3"
iroh = { version = "0.96", optional = true }
-swactor-ci = { path = "../ci", optional = true }
[features]
default = ["distribution"]
@@ -26,7 +28,6 @@ distribution = ["dep:distribution"]
node = ["distribution", "dep:clap", "swactor/transport", "tcp"]
tcp = ["distribution/tcp"]
iroh = ["distribution/iroh", "dep:iroh"]
-ci = ["dep:swactor-ci"]
[[bin]]
name = "swactor-tui"
diff --git a/crates/runtime-dashboard/README.md b/crates/dashboard/README.md
similarity index 100%
rename from crates/runtime-dashboard/README.md
rename to crates/dashboard/README.md
diff --git a/crates/runtime-dashboard/examples/bench_dashboard.rs b/crates/dashboard/examples/bench_dashboard.rs
similarity index 94%
rename from crates/runtime-dashboard/examples/bench_dashboard.rs
rename to crates/dashboard/examples/bench_dashboard.rs
index aef4283..a2ed48f 100644
--- a/crates/runtime-dashboard/examples/bench_dashboard.rs
+++ b/crates/dashboard/examples/bench_dashboard.rs
@@ -5,8 +5,8 @@ use swactor::actor::{ActorAddress, ActorInterface, Ctx};
use swactor::config::{BackoffPolicy, RuntimeConfig};
use swactor::runtime::Runtime;
-use runtime_dashboard::collector::StatsCollector;
-use runtime_dashboard::{start_dashboard, DashboardConfig};
+use dashboard::collector::StatsCollector;
+use dashboard::{start_dashboard, DashboardConfig};
// ---------------------------------------------------------------------------
// Actors
@@ -102,7 +102,7 @@ fn run_for(duration: Duration, mut tick: impl FnMut()) {
// Scenarios
// ---------------------------------------------------------------------------
-fn scenario_single_actor(dash: &runtime_dashboard::DashboardHandle) {
+fn scenario_single_actor(dash: &dashboard::DashboardHandle) {
eprintln!(" [1/4] Single-actor bombardment (5s)");
let collector = StatsCollector::new(4);
let mut rt = Runtime::new(bench_config(4, 64, 100_000));
@@ -122,7 +122,7 @@ fn scenario_single_actor(dash: &runtime_dashboard::DashboardHandle) {
handle.join();
}
-fn scenario_multi_actor(dash: &runtime_dashboard::DashboardHandle) {
+fn scenario_multi_actor(dash: &dashboard::DashboardHandle) {
eprintln!(" [2/4] Multi-actor fan-out (5s)");
let collector = StatsCollector::new(4);
let mut rt = Runtime::new(bench_config(4, 128, 10_000));
@@ -146,7 +146,7 @@ fn scenario_multi_actor(dash: &runtime_dashboard::DashboardHandle) {
handle.join();
}
-fn scenario_ring(dash: &runtime_dashboard::DashboardHandle) {
+fn scenario_ring(dash: &dashboard::DashboardHandle) {
eprintln!(" [3/4] Ring topology (5s)");
let ring_size = 100;
let collector = StatsCollector::new(4);
@@ -182,7 +182,7 @@ fn scenario_ring(dash: &runtime_dashboard::DashboardHandle) {
handle.join();
}
-fn scenario_spawn_storm(dash: &runtime_dashboard::DashboardHandle) {
+fn scenario_spawn_storm(dash: &dashboard::DashboardHandle) {
eprintln!(" [4/4] Spawn storm (5s)");
let collector = StatsCollector::new(4);
let mut rt = Runtime::new(bench_config(4, 50_000, 1_024));
diff --git a/crates/runtime-dashboard/examples/dashboard_demo.rs b/crates/dashboard/examples/dashboard_demo.rs
similarity index 98%
rename from crates/runtime-dashboard/examples/dashboard_demo.rs
rename to crates/dashboard/examples/dashboard_demo.rs
index f115b2f..0baf838 100644
--- a/crates/runtime-dashboard/examples/dashboard_demo.rs
+++ b/crates/dashboard/examples/dashboard_demo.rs
@@ -13,9 +13,9 @@ use distribution::swim::node::NodeAction;
use distribution::swim::probe::SwimConfig;
use distribution::types::NodeId;
-use runtime_dashboard::collector::StatsCollector;
-use runtime_dashboard::distribution_collector::DistributionStatsProvider;
-use runtime_dashboard::{start_dashboard, DashboardConfig};
+use dashboard::collector::StatsCollector;
+use dashboard::distribution_collector::DistributionStatsProvider;
+use dashboard::{start_dashboard, DashboardConfig};
// ── Demo actors ─────────────────────────────────────────────────────────
diff --git a/crates/runtime-dashboard/examples/record_and_replay_demo.rs b/crates/dashboard/examples/record_and_replay_demo.rs
similarity index 97%
rename from crates/runtime-dashboard/examples/record_and_replay_demo.rs
rename to crates/dashboard/examples/record_and_replay_demo.rs
index 71e0494..13d5292 100644
--- a/crates/runtime-dashboard/examples/record_and_replay_demo.rs
+++ b/crates/dashboard/examples/record_and_replay_demo.rs
@@ -7,8 +7,8 @@ use swactor::actor::{ActorAddress, ActorInterface, Ctx};
use swactor::config::RuntimeConfig;
use swactor::runtime::Runtime;
-use runtime_dashboard::collector::StatsCollector;
-use runtime_dashboard::{serve_replay, start_dashboard, DashboardConfig, ReplayConfig};
+use dashboard::collector::StatsCollector;
+use dashboard::{serve_replay, start_dashboard, DashboardConfig, ReplayConfig};
// ── Demo actors ─────────────────────────────────────────────────────────
diff --git a/crates/runtime-dashboard/src/actor_detail_html.rs b/crates/dashboard/src/actor_detail_html.rs
similarity index 95%
rename from crates/runtime-dashboard/src/actor_detail_html.rs
rename to crates/dashboard/src/actor_detail_html.rs
index c5c2c27..4b4c41e 100644
--- a/crates/runtime-dashboard/src/actor_detail_html.rs
+++ b/crates/dashboard/src/actor_detail_html.rs
@@ -135,8 +135,11 @@ pub const ACTOR_DETAIL_HTML: &str = r##"
+
@@ -237,7 +240,14 @@ pub const ACTOR_DETAIL_HTML: &str = r##"
if (!actor) return;
var hex = formatAddr(actor.address);
- document.getElementById('addrBreadcrumb').textContent = shortAddr(hex);
+ if (actor.name) {
+ document.getElementById('addrBreadcrumb').textContent = actor.name;
+ document.getElementById('nameRow').style.display = '';
+ document.getElementById('addrName').textContent = actor.name;
+ } else {
+ document.getElementById('addrBreadcrumb').textContent = shortAddr(hex);
+ document.getElementById('nameRow').style.display = 'none';
+ }
document.getElementById('addrFull').textContent = hex;
document.getElementById('addrWorker').textContent = 'W' + actor.worker_id;
diff --git a/crates/runtime-dashboard/src/actors_html.rs b/crates/dashboard/src/actors_html.rs
similarity index 95%
rename from crates/runtime-dashboard/src/actors_html.rs
rename to crates/dashboard/src/actors_html.rs
index 2c139fb..9595175 100644
--- a/crates/runtime-dashboard/src/actors_html.rs
+++ b/crates/dashboard/src/actors_html.rs
@@ -478,7 +478,8 @@ pub const ACTORS_HTML: &str = r##"
if (filter) {
var hex = addrToHex(a.address).toLowerCase();
var msgType = (a.last_msg_type || '').toLowerCase();
- if (hex.indexOf(filter) < 0 && ('w' + a.worker_id).indexOf(filter) < 0 && msgType.indexOf(filter) < 0) {
+ var actorName = (a.name || '').toLowerCase();
+ if (hex.indexOf(filter) < 0 && ('w' + a.worker_id).indexOf(filter) < 0 && msgType.indexOf(filter) < 0 && actorName.indexOf(filter) < 0) {
return false;
}
}
@@ -542,8 +543,11 @@ pub const ACTORS_HTML: &str = r##"
tr.className = 'clickable' + (fullHex === focusedAddrHex ? ' focused' : '');
if (a.poisoned) tr.style.opacity = '0.6';
tr.setAttribute('data-addr', fullHex);
+ var addrCell = a.name
+ ? '
' + escapeHtml(a.name) + ' ' + escapeHtml(hex) + '' + (a.poisoned ? ' DEAD' : '') + ' | '
+ : '
' + escapeHtml(hex) + (a.poisoned ? ' DEAD' : '') + ' | ';
tr.innerHTML =
- '
' + escapeHtml(hex) + (a.poisoned ? ' DEAD' : '') + ' | ' +
+ addrCell +
'
W' + a.worker_id + ' | ' +
'
' + a.mailbox_depth + ' | ' +
'
' + (a.messages_processed || 0).toLocaleString() + ' | ' +
@@ -593,8 +597,14 @@ pub const ACTORS_HTML: &str = r##"
return;
}
- document.getElementById('detailAddr').innerHTML = '
' + escapeHtml(addrToHex(actor.address)) + '';
- document.getElementById('detailFullAddr').innerHTML = '
' + escapeHtml(focusedAddrHex) + '';
+ var detailAddrText = actor.name
+ ? '
' + escapeHtml(actor.name) + ''
+ : '
' + escapeHtml(addrToHex(actor.address)) + '';
+ document.getElementById('detailAddr').innerHTML = detailAddrText;
+ var detailFullText = actor.name
+ ? '
' + escapeHtml(actor.name) + ' ' + escapeHtml(focusedAddrHex) + ''
+ : '
' + escapeHtml(focusedAddrHex) + '';
+ document.getElementById('detailFullAddr').innerHTML = detailFullText;
document.getElementById('detailWorker').textContent = 'W' + actor.worker_id;
document.getElementById('detailMailbox').textContent = actor.mailbox_depth;
document.getElementById('detailMsgCount').textContent = (actor.messages_processed || 0).toLocaleString();
diff --git a/crates/runtime-dashboard/src/bin/swactor-node.rs b/crates/dashboard/src/bin/swactor-node.rs
similarity index 97%
rename from crates/runtime-dashboard/src/bin/swactor-node.rs
rename to crates/dashboard/src/bin/swactor-node.rs
index d74dbfa..d2cd4f0 100644
--- a/crates/runtime-dashboard/src/bin/swactor-node.rs
+++ b/crates/dashboard/src/bin/swactor-node.rs
@@ -14,9 +14,9 @@ use distribution::registry::RegistryConfig;
use distribution::snapshot::DistributionNodeSnapshot;
use distribution::swim::probe::SwimConfig;
-use runtime_dashboard::collector::StatsCollector;
-use runtime_dashboard::distribution_collector::DistributionStatsProvider;
-use runtime_dashboard::{start_dashboard, DashboardConfig};
+use dashboard::collector::StatsCollector;
+use dashboard::distribution_collector::DistributionStatsProvider;
+use dashboard::{start_dashboard, DashboardConfig};
// ── CLI ──────────────────────────────────────────────────────────────────
@@ -95,6 +95,7 @@ fn main() {
..Default::default()
});
dash.install_tracing();
+ dash.start_http_standalone();
// Create actor runtime
let num_threads = 2;
@@ -154,7 +155,7 @@ fn run_tcp(
args: Args,
node_config: DistributedNodeConfig,
handle: &swactor::runtime::RuntimeHandle,
- dash: &runtime_dashboard::DashboardHandle,
+ dash: &dashboard::DashboardHandle,
stop: &Arc
,
) {
use distribution::driver::NodeDriver;
@@ -209,7 +210,7 @@ fn run_iroh(
args: Args,
node_config: DistributedNodeConfig,
handle: &swactor::runtime::RuntimeHandle,
- dash: &runtime_dashboard::DashboardHandle,
+ dash: &dashboard::DashboardHandle,
stop: &Arc,
) {
use distribution::iroh_driver::{IrohDriver, IrohDriverConfig};
diff --git a/crates/runtime-dashboard/src/bin/tui.rs b/crates/dashboard/src/bin/tui.rs
similarity index 72%
rename from crates/runtime-dashboard/src/bin/tui.rs
rename to crates/dashboard/src/bin/tui.rs
index 00060d9..1b58344 100644
--- a/crates/runtime-dashboard/src/bin/tui.rs
+++ b/crates/dashboard/src/bin/tui.rs
@@ -1,5 +1,5 @@
-use runtime_dashboard::tui::types::RuntimeEndpoint;
-use runtime_dashboard::tui::{start_tui_remote, TuiConfig};
+use dashboard::tui::types::RuntimeEndpoint;
+use dashboard::tui::{start_tui_remote, TuiConfig};
fn main() -> std::io::Result<()> {
let url = std::env::args()
diff --git a/crates/runtime-dashboard/src/ci_collector.rs b/crates/dashboard/src/ci_collector.rs
similarity index 89%
rename from crates/runtime-dashboard/src/ci_collector.rs
rename to crates/dashboard/src/ci_collector.rs
index 85b321e..8629fa2 100644
--- a/crates/runtime-dashboard/src/ci_collector.rs
+++ b/crates/dashboard/src/ci_collector.rs
@@ -2,7 +2,39 @@
use serde::{Deserialize, Serialize};
-use swactor_ci::{JobId, JobStatus, PipelineId, PipelineStatus};
+// CI types defined locally to avoid a cyclic dependency with swactor-ci.
+
+/// Unique identifier for a pipeline execution.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct PipelineId(pub u64);
+
+/// Unique identifier for a job within a pipeline.
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct JobId {
+ pub pipeline_id: PipelineId,
+ pub job_name: String,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+pub enum JobStatus {
+ Pending,
+ WaitingForProvisioner,
+ Provisioning,
+ Running,
+ Passed,
+ Failed { reason: String },
+ Skipped,
+ Interrupted,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+pub enum PipelineStatus {
+ Pending,
+ Running,
+ Passed,
+ Failed,
+ Error { reason: String },
+}
// ─── Stats Provider ─────────────────────────────────────────────────────────
diff --git a/crates/runtime-dashboard/src/collector.rs b/crates/dashboard/src/collector.rs
similarity index 80%
rename from crates/runtime-dashboard/src/collector.rs
rename to crates/dashboard/src/collector.rs
index 47837c3..ecd45b7 100644
--- a/crates/runtime-dashboard/src/collector.rs
+++ b/crates/dashboard/src/collector.rs
@@ -6,6 +6,7 @@
use std::sync::{Arc, RwLock};
+use swactor::runtime::Runtime;
use swactor::stats::{ActorInfo, ActorSnapshot, RuntimeStats, StatsHook};
/// Collects per-actor snapshots pushed by worker threads.
@@ -48,6 +49,21 @@ impl crate::command::StatsEnricher for StatsCollector {
}
}
+/// Enrich actor names from the runtime's StdExtension name registry.
+pub fn enrich_names(stats: &mut RuntimeStats, runtime: &Runtime) {
+ let ext = match runtime.extension() {
+ Some(ext) => ext,
+ None => return,
+ };
+ let std_ext = match ext.as_any().downcast_ref::() {
+ Some(ext) => ext,
+ None => return,
+ };
+ for actor in &mut stats.actor_details {
+ actor.name = std_ext.resolve_name(&actor.address);
+ }
+}
+
impl StatsHook for StatsCollector {
fn on_tick(&self, worker_id: usize, snapshots: &[ActorSnapshot]) {
if let Some(slot) = self.slots.get(worker_id) {
@@ -60,6 +76,7 @@ impl StatsHook for StatsCollector {
last_msg_type: s.last_msg_type.map(|t| t.to_string()),
messages_processed: s.messages_processed,
poisoned: s.poisoned,
+ name: None,
message_type_counts: s.message_type_counts.iter().map(|(k, v)| (k.to_string(), *v)).collect(),
}));
}
diff --git a/crates/runtime-dashboard/src/command/builtins.rs b/crates/dashboard/src/command/builtins.rs
similarity index 100%
rename from crates/runtime-dashboard/src/command/builtins.rs
rename to crates/dashboard/src/command/builtins.rs
diff --git a/crates/runtime-dashboard/src/command/mod.rs b/crates/dashboard/src/command/mod.rs
similarity index 100%
rename from crates/runtime-dashboard/src/command/mod.rs
rename to crates/dashboard/src/command/mod.rs
diff --git a/crates/runtime-dashboard/src/command/parse.rs b/crates/dashboard/src/command/parse.rs
similarity index 100%
rename from crates/runtime-dashboard/src/command/parse.rs
rename to crates/dashboard/src/command/parse.rs
diff --git a/crates/runtime-dashboard/src/dashboard_html.rs b/crates/dashboard/src/dashboard_html.rs
similarity index 95%
rename from crates/runtime-dashboard/src/dashboard_html.rs
rename to crates/dashboard/src/dashboard_html.rs
index 0054723..0aa4f7f 100644
--- a/crates/runtime-dashboard/src/dashboard_html.rs
+++ b/crates/dashboard/src/dashboard_html.rs
@@ -356,6 +356,14 @@ pub const DASHBOARD_HTML: &str = r##"
renderWorkerCards(data);
+ var nameMap = {};
+ if (data.actor_details) {
+ data.actor_details.forEach(function(a) {
+ var h = formatAddr(a.address);
+ if (a.name) nameMap[h] = a.name;
+ });
+ }
+
var tbody = document.getElementById('actorTableBody');
tbody.innerHTML = '';
if (data.actors) {
@@ -372,7 +380,13 @@ pub const DASHBOARD_HTML: &str = r##"
hex += '\u2026';
}
var tr = document.createElement('tr');
- tr.innerHTML = '' + hex + ' | W' + wid + ' | ';
+ var addrCell;
+ if (nameMap[hex]) {
+ addrCell = '' + escapeHtml(nameMap[hex]) + ' ' + hex + ' | ';
+ } else {
+ addrCell = '' + hex + ' | ';
+ }
+ tr.innerHTML = addrCell + 'W' + wid + ' | ';
tbody.appendChild(tr);
});
if (data.actors.length > 200) {
@@ -493,7 +507,13 @@ pub const DASHBOARD_HTML: &str = r##"
var msgShort = hasMsg ? shortTypeName(a.last_msg_type) : 'none';
var msgClass = hasMsg ? 'msg-type' : 'msg-type none';
var title = hasMsg ? ' title="' + escapeHtml(a.last_msg_type) + '"' : '';
- rows += '| ' + hex + ' | ' +
+ var addrHtml;
+ if (a.name) {
+ addrHtml = '' + escapeHtml(a.name) + ' ' + hex + ' | ';
+ } else {
+ addrHtml = '' + hex + ' | ';
+ }
+ rows += '
' + addrHtml +
'| ' + a.mailbox_depth + ' | ' +
'' + escapeHtml(msgShort) + ' |
';
});
diff --git a/crates/runtime-dashboard/src/datastore_collector.rs b/crates/dashboard/src/datastore_collector.rs
similarity index 100%
rename from crates/runtime-dashboard/src/datastore_collector.rs
rename to crates/dashboard/src/datastore_collector.rs
diff --git a/crates/runtime-dashboard/src/datastore_html.rs b/crates/dashboard/src/datastore_html.rs
similarity index 100%
rename from crates/runtime-dashboard/src/datastore_html.rs
rename to crates/dashboard/src/datastore_html.rs
diff --git a/crates/runtime-dashboard/src/distribution_collector.rs b/crates/dashboard/src/distribution_collector.rs
similarity index 100%
rename from crates/runtime-dashboard/src/distribution_collector.rs
rename to crates/dashboard/src/distribution_collector.rs
diff --git a/crates/runtime-dashboard/src/distribution_html.rs b/crates/dashboard/src/distribution_html.rs
similarity index 97%
rename from crates/runtime-dashboard/src/distribution_html.rs
rename to crates/dashboard/src/distribution_html.rs
index b7b78f0..00ff106 100644
--- a/crates/runtime-dashboard/src/distribution_html.rs
+++ b/crates/dashboard/src/distribution_html.rs
@@ -94,6 +94,19 @@ pub const DISTRIBUTION_HTML: &str = r##"
flex: 1; overflow-y: auto; font-size: 11px;
}
+ .relay-badge {
+ display: inline-block;
+ background: #14b8a6;
+ color: #fff;
+ font-size: 9px;
+ font-weight: 700;
+ padding: 1px 5px;
+ border-radius: 3px;
+ margin-left: 6px;
+ vertical-align: middle;
+ letter-spacing: 0.5px;
+ }
+
.ego-hint {
position: absolute; bottom: 12px; left: 12px; font-size: 10px;
color: #555; pointer-events: none;
@@ -600,6 +613,18 @@ pub const DISTRIBUTION_HTML: &str = r##"
ctx.stroke();
}
+ // Teal ring around relay nodes
+ var isRelay = (i === 0 && data && data.relay_url)
+ || (i > 0 && data && data.members[i-1] && data.members[i-1].relay_url);
+ if (isRelay) {
+ ctx.beginPath();
+ ctx.arc(posX[i], posY[i], nr + 3/vs, 0, Math.PI * 2);
+ ctx.lineWidth = 2/vs;
+ ctx.strokeStyle = '#14b8a6';
+ ctx.globalAlpha = opacity * 0.9;
+ ctx.stroke();
+ }
+
ctx.globalAlpha = 1;
// Label (name for self, short ID for others)
@@ -699,9 +724,12 @@ pub const DISTRIBUTION_HTML: &str = r##"
var tr = document.createElement('tr');
var idCell = m.node_id.substring(0, 16) + '\u2026';
if (m.label) idCell = m.label + ' (' + m.node_id.substring(0, 8) + ')';
+ var relayBadge = m.relay_url
+ ? ' RELAY'
+ : '';
tr.innerHTML =
'' + m.state + ' | ' +
- '' + idCell + ' | ' +
+ '' + idCell + relayBadge + ' | ' +
'' + m.addr + ' | ' +
'' + m.incarnation + ' | ';
body.appendChild(tr);
diff --git a/crates/runtime-dashboard/src/history.rs b/crates/dashboard/src/history.rs
similarity index 99%
rename from crates/runtime-dashboard/src/history.rs
rename to crates/dashboard/src/history.rs
index 51be11d..8a0b629 100644
--- a/crates/runtime-dashboard/src/history.rs
+++ b/crates/dashboard/src/history.rs
@@ -253,6 +253,7 @@ mod tests {
fn make_actor(id: u8, worker: usize, depth: usize, msgs: u64) -> ActorInfo {
ActorInfo {
address: ActorAddress([id; 32]),
+ name: None,
worker_id: worker,
mailbox_depth: depth,
last_msg_type: None,
diff --git a/crates/runtime-dashboard/src/investigate.rs b/crates/dashboard/src/investigate.rs
similarity index 100%
rename from crates/runtime-dashboard/src/investigate.rs
rename to crates/dashboard/src/investigate.rs
diff --git a/crates/runtime-dashboard/src/layer.rs b/crates/dashboard/src/layer.rs
similarity index 100%
rename from crates/runtime-dashboard/src/layer.rs
rename to crates/dashboard/src/layer.rs
diff --git a/crates/runtime-dashboard/src/lib.rs b/crates/dashboard/src/lib.rs
similarity index 75%
rename from crates/runtime-dashboard/src/lib.rs
rename to crates/dashboard/src/lib.rs
index 14522d2..9c3ce92 100644
--- a/crates/runtime-dashboard/src/lib.rs
+++ b/crates/dashboard/src/lib.rs
@@ -23,7 +23,6 @@ pub mod distribution_collector;
mod datastore_html;
pub mod datastore_collector;
-#[cfg(feature = "ci")]
pub mod ci_collector;
use std::io;
@@ -43,6 +42,9 @@ use crate::history::{DashboardHistory, HistoryConfig};
use crate::layer::{now_ms, DashboardLayer, EventStore};
use crate::trace::{RuntimeTrace, TimestampedStats};
+/// Peer info sent through the join channel: (public_key, optional_relay_url).
+pub type JoinPeerInfo = ([u8; 32], Option);
+
/// Configuration for the runtime dashboard.
#[derive(Debug, Clone)]
pub struct DashboardConfig {
@@ -92,18 +94,19 @@ pub struct DashboardHandle {
runtime: Arc>>>,
collector: Arc>>>,
shutdown: Arc,
+ shutdown_notify: Arc,
stats_timeline: Arc>,
history: Arc,
recording: bool,
+ port: u16,
#[cfg(feature = "distribution")]
distribution: Arc>>>,
datastore: Arc>>>,
datastore_factory: Arc>>>,
- #[cfg(feature = "ci")]
ci: Arc>>>,
- dashboard_token: Arc>>,
peer_auth: Arc>>>>,
- join_sender: Arc>>>,
+ join_sender: Arc>>>,
+ standalone_rt: Mutex