Promote pipeline-parallel-inference to a first-class app and consolidate observability on the datastream wire, decoupling the dashboard crate from `distribution`. - apps/pipeline-parallel-inference: move the example out of `examples/` into `apps/` as its own workspace, rename binaries to `pp-worker`/`pp-orchestrator`, and strip release binaries - cluster: add `ClusterNode`, a synchronous facade over the actorized distribution protocol (IrohDriver + per-node Runtime hosting Swim/Registry/Metadata/Directory actors with a `MembershipFanout`), replacing ad-hoc `driver.node()`/`tick()` call sites - fleet: add per-node fleet telemetry that ships identity/resource records as `DatastreamFrame`s over the cluster transport to the orchestrator's `DatastreamSink`, folded into a `FleetView` on a 3s tick - provision: add best-effort, opt-in SSH boot-phase telemetry (`PP_DEPLOY_KEY`) that streams rented-node boot logs onto the orchestrator's datastream as `proc.boot.<stage>.*` - dashboard: rewire the crate dependency from `distribution` to `datastream`, drop the standalone `swactor-datastream-dashboard` binary, and rewrite `datastream_source.rs` to demux per-node frames into Overview/Distribution/Fleet views with live-node TTL filtering - distribution: refresh dist/netmap plugin copy and README from "Kademlia routing" to gossip-directory terminology Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
108 lines
2.7 KiB
TOML
108 lines
2.7 KiB
TOML
# Goal 2 — real detection (the central gap). A steady 4-node SWIM mesh; one
|
|
# node is genuinely killed mid-run (peer_kill: ticks stopped, in-flight and
|
|
# future deliveries dropped), so a survivor's probe TRULY times out — not an
|
|
# injected death. After `probe_timeout + suspicion_timeout`, every survivor must
|
|
# converge on the killed node being Dead (`peer_detected_dead_within`, the mirror
|
|
# of `dead_peer_resurrects_within`).
|
|
# Expected verdict: pass-now.
|
|
|
|
name = "peer_kill_detection"
|
|
seed = 11
|
|
duration_ns = 50_000_000_000 # 50 s
|
|
|
|
[default_tick]
|
|
period_ns = 200_000_000
|
|
|
|
[default_link]
|
|
latency_ns = 5_000_000
|
|
jitter_stddev_ns = 1_000_000
|
|
loss_prob_ppm = 0
|
|
reorder_prob_ppm = 0
|
|
bandwidth_bps = 100_000_000
|
|
cold_dial_penalty_ns = 50_000_000
|
|
cache_warm_after_ns = 100_000_000
|
|
cache_invalidate_after_idle_ns = 30_000_000_000
|
|
|
|
# Brisk timing so detection (≈ 2·probe_timeout + suspicion_timeout) completes
|
|
# well inside the run: probe every 1 s, 1 s per phase, 5 s suspicion window.
|
|
[[peers]]
|
|
id = "a"
|
|
kind = "swim"
|
|
initial_state = "alive"
|
|
kind_config = { probe_interval_ns = 1_000_000_000, probe_timeout_ns = 1_000_000_000, suspicion_timeout_ns = 5_000_000_000 }
|
|
[[peers]]
|
|
id = "b"
|
|
kind = "swim"
|
|
initial_state = "alive"
|
|
kind_config = { probe_interval_ns = 1_000_000_000, probe_timeout_ns = 1_000_000_000, suspicion_timeout_ns = 5_000_000_000 }
|
|
[[peers]]
|
|
id = "c"
|
|
kind = "swim"
|
|
initial_state = "alive"
|
|
kind_config = { probe_interval_ns = 1_000_000_000, probe_timeout_ns = 1_000_000_000, suspicion_timeout_ns = 5_000_000_000 }
|
|
[[peers]]
|
|
id = "d"
|
|
kind = "swim"
|
|
initial_state = "alive"
|
|
kind_config = { probe_interval_ns = 1_000_000_000, probe_timeout_ns = 1_000_000_000, suspicion_timeout_ns = 5_000_000_000 }
|
|
|
|
# Full mesh — every survivor can directly probe the victim, so detection is a
|
|
# genuine probe timeout, not a topology artifact.
|
|
[[links]]
|
|
from = "a"
|
|
to = "b"
|
|
[[links]]
|
|
from = "b"
|
|
to = "a"
|
|
[[links]]
|
|
from = "a"
|
|
to = "c"
|
|
[[links]]
|
|
from = "c"
|
|
to = "a"
|
|
[[links]]
|
|
from = "a"
|
|
to = "d"
|
|
[[links]]
|
|
from = "d"
|
|
to = "a"
|
|
[[links]]
|
|
from = "b"
|
|
to = "c"
|
|
[[links]]
|
|
from = "c"
|
|
to = "b"
|
|
[[links]]
|
|
from = "b"
|
|
to = "d"
|
|
[[links]]
|
|
from = "d"
|
|
to = "b"
|
|
[[links]]
|
|
from = "c"
|
|
to = "d"
|
|
[[links]]
|
|
from = "d"
|
|
to = "c"
|
|
|
|
# Genuinely silence "d" at 15 s.
|
|
[[mutations]]
|
|
kind = "peer_kill"
|
|
at_ns = 15_000_000_000
|
|
peer = "d"
|
|
|
|
# Snapshots across the post-detection window (the killed peer "d" is excluded
|
|
# from snapshots, so only the survivors are observed).
|
|
[[snapshots]]
|
|
at_ns = 30_000_000_000
|
|
[[snapshots]]
|
|
at_ns = 36_000_000_000
|
|
[[snapshots]]
|
|
at_ns = 42_000_000_000
|
|
|
|
# Goal 2: every survivor converges on "d" = Dead within the detection window.
|
|
[[assertions]]
|
|
kind = "peer_detected_dead_within"
|
|
peer = "d"
|
|
after_ns = 15_000_000_000
|
|
within_ns = 30_000_000_000
|