use std::collections::HashMap; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; use swactor::actor::ActorAddress; use crate::protocol::VersionedValue; // ── Shared handles ─────────────────────────────────────────────────────── /// Shared, append-only event log. pub type EventLog = Arc>>; /// Shared tick counter — the simulation harness increments this. pub type TickCounter = Arc; /// Maps actor addresses to human-readable names like `"node-0"`. pub type NameRegistry = Arc>>; // ── TraceContext ───────────────────────────────────────────────────────── /// Bundles the three shared handles needed for tracing into one value. pub struct TraceContext { pub event_log: EventLog, pub tick_counter: TickCounter, pub name_registry: NameRegistry, } impl TraceContext { pub fn current_tick(&self) -> u64 { self.tick_counter.load(Ordering::Relaxed) } pub fn resolve_name(&self, addr: ActorAddress) -> String { self.name_registry .lock() .unwrap() .get(&addr) .cloned() .unwrap_or_else(|| format!("{:?}", &addr.0[..4])) } pub fn record_event(&self, event: GossipEvent) { self.event_log.lock().unwrap().push(event); } } // ── Event types ────────────────────────────────────────────────────────── #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GossipEvent { pub tick: u64, pub node_name: String, pub node_addr: ActorAddress, pub thread_name: Option, pub kind: GossipEventKind, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum GossipEventKind { /// A local `Set { key, .. }` was processed. LocalSet { key: String }, /// `DoGossipRound` chose a peer and sent a Push. GossipRoundStarted { target_name: String }, /// `DoGossipRound` had no peers. GossipRoundNoPeers, /// Received a Push from another node. PushReceived { from_name: String, keys_updated: usize, }, /// Received a Query. QueryReceived { key: String }, /// A peer was added. PeerAdded { peer_name: String }, /// A peer was removed. PeerRemoved { peer_name: String }, /// Full state snapshot (requested via `TakeSnapshot`). StateSnapshot { snapshot: NodeSnapshot }, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct NodeSnapshot { pub entries: HashMap, pub peer_count: usize, } // ── Simulation trace (complete run output) ─────────────────────────────── #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SimulationTrace { pub name: String, pub node_names: Vec, pub node_addrs: Vec, pub topology_edges: Vec<(String, String)>, pub events: Vec, pub snapshots_per_round: Vec>, pub num_rounds: usize, pub total_keys: usize, }