sparrow/streaming/
lane.rs1use std::collections::HashMap;
7use std::time::Instant;
8
9struct AgentLane {
11 name: String,
12 status: String,
13 started: Instant,
14}
15
16pub struct LaneDisplay {
18 lanes: HashMap<String, AgentLane>,
19}
20
21impl LaneDisplay {
22 pub fn new() -> Self {
24 Self {
25 lanes: HashMap::new(),
26 }
27 }
28
29 pub fn add_lane(&mut self, name: &str) {
31 self.lanes.insert(
32 name.to_string(),
33 AgentLane {
34 name: name.to_string(),
35 status: "starting...".to_string(),
36 started: Instant::now(),
37 },
38 );
39 }
40
41 pub fn update_lane(&mut self, name: &str, status: &str) {
43 if let Some(lane) = self.lanes.get_mut(name) {
44 lane.status = status.to_string();
45 }
46 }
47
48 pub fn remove_lane(&mut self, name: &str) {
50 self.lanes.remove(name);
51 }
52
53 pub fn render(&self) {
55 let mut sorted: Vec<&AgentLane> = self.lanes.values().collect();
57 sorted.sort_by(|a, b| a.name.cmp(&b.name));
58
59 for lane in &sorted {
60 let elapsed = lane.started.elapsed().as_secs();
61 eprintln!(
62 " \x1b[36m[{elapsed:>3}s]\x1b[0m \x1b[1m{}\x1b[0m — {}",
63 lane.name, lane.status
64 );
65 }
66 }
67
68 pub fn is_empty(&self) -> bool {
70 self.lanes.is_empty()
71 }
72
73 pub fn len(&self) -> usize {
75 self.lanes.len()
76 }
77}
78
79impl Default for LaneDisplay {
80 fn default() -> Self {
81 Self::new()
82 }
83}