ralph_core/event_loop/loop_state.rs
1//! Loop state tracking for the event loop.
2//!
3//! This module contains the `LoopState` struct that tracks the current
4//! state of the orchestration loop including iteration count, failures,
5//! timing, and hat activation tracking.
6
7use ralph_proto::HatId;
8use std::collections::{HashMap, HashSet};
9use std::time::{Duration, Instant};
10
11/// Current state of the event loop.
12#[derive(Debug)]
13pub struct LoopState {
14 /// Current iteration number (1-indexed).
15 pub iteration: u32,
16 /// Number of consecutive failures.
17 pub consecutive_failures: u32,
18 /// Cumulative cost in USD (if tracked).
19 pub cumulative_cost: f64,
20 /// When the loop started.
21 pub started_at: Instant,
22 /// The last hat that executed.
23 pub last_hat: Option<HatId>,
24 /// Consecutive blocked events from the same hat.
25 pub consecutive_blocked: u32,
26 /// Hat that emitted the last blocked event.
27 pub last_blocked_hat: Option<HatId>,
28 /// Per-task block counts for task-level thrashing detection.
29 pub task_block_counts: HashMap<String, u32>,
30 /// Tasks that have been abandoned after 3+ blocks.
31 pub abandoned_tasks: Vec<String>,
32 /// Count of times planner dispatched an already-abandoned task.
33 pub abandoned_task_redispatches: u32,
34 /// Consecutive malformed JSONL lines encountered (for validation backpressure).
35 pub consecutive_malformed_events: u32,
36
37 /// Per-hat activation counts (used for max_activations).
38 pub hat_activation_counts: HashMap<HatId, u32>,
39
40 /// Hats for which `<hat_id>.exhausted` has been emitted.
41 pub exhausted_hats: HashSet<HatId>,
42}
43
44impl Default for LoopState {
45 fn default() -> Self {
46 Self {
47 iteration: 0,
48 consecutive_failures: 0,
49 cumulative_cost: 0.0,
50 started_at: Instant::now(),
51 last_hat: None,
52 consecutive_blocked: 0,
53 last_blocked_hat: None,
54 task_block_counts: HashMap::new(),
55 abandoned_tasks: Vec::new(),
56 abandoned_task_redispatches: 0,
57 consecutive_malformed_events: 0,
58 hat_activation_counts: HashMap::new(),
59 exhausted_hats: HashSet::new(),
60 }
61 }
62}
63
64impl LoopState {
65 /// Creates a new loop state.
66 pub fn new() -> Self {
67 Self::default()
68 }
69
70 /// Returns the elapsed time since the loop started.
71 pub fn elapsed(&self) -> Duration {
72 self.started_at.elapsed()
73 }
74}