ralph_workflow/pipeline/
mod.rs1#![deny(unsafe_code)]
20
21mod clipboard;
22mod fallback;
23pub mod idle_timeout;
24pub mod logfile;
25mod model_flag;
26mod prompt;
27mod runner;
28pub mod session;
29mod types;
30
31pub use fallback::OutputValidator;
32pub use prompt::{run_with_prompt, PipelineRuntime, PromptCommand};
33pub use runner::{
34 run_with_fallback_and_validator, run_xsd_retry_with_session, FallbackConfig, XsdRetryConfig,
35};
36pub use types::{AgentPhaseGuard, Stats};
37
38use std::time::{Duration, Instant};
41
42#[derive(Clone)]
44pub struct Timer {
45 start_time: Instant,
46 phase_start: Instant,
47}
48
49impl Timer {
50 pub fn new() -> Self {
52 let now = Instant::now();
53 Self {
54 start_time: now,
55 phase_start: now,
56 }
57 }
58
59 pub fn start_phase(&mut self) {
61 self.phase_start = Instant::now();
62 }
63
64 pub fn elapsed(&self) -> Duration {
66 self.start_time.elapsed()
67 }
68
69 pub fn phase_elapsed(&self) -> Duration {
71 self.phase_start.elapsed()
72 }
73
74 pub fn format_duration(duration: Duration) -> String {
76 let total_secs = duration.as_secs();
77 let mins = total_secs / 60;
78 let secs = total_secs % 60;
79 format!("{mins}m {secs:02}s")
80 }
81
82 pub fn elapsed_formatted(&self) -> String {
84 Self::format_duration(self.elapsed())
85 }
86
87 pub fn phase_elapsed_formatted(&self) -> String {
89 Self::format_duration(self.phase_elapsed())
90 }
91}
92
93impl Default for Timer {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99#[cfg(test)]
100mod timer_tests {
101 use super::*;
102 use std::thread;
103
104 #[test]
105 fn test_format_duration_zero() {
106 let d = Duration::from_secs(0);
107 assert_eq!(Timer::format_duration(d), "0m 00s");
108 }
109
110 #[test]
111 fn test_format_duration_seconds() {
112 let d = Duration::from_secs(30);
113 assert_eq!(Timer::format_duration(d), "0m 30s");
114 }
115
116 #[test]
117 fn test_format_duration_minutes() {
118 let d = Duration::from_secs(65);
119 assert_eq!(Timer::format_duration(d), "1m 05s");
120 }
121
122 #[test]
123 fn test_format_duration_large() {
124 let d = Duration::from_secs(3661);
125 assert_eq!(Timer::format_duration(d), "61m 01s");
126 }
127
128 #[test]
129 fn test_timer_elapsed() {
130 let timer = Timer::new();
131 thread::sleep(Duration::from_millis(10));
132 assert!(timer.elapsed() >= Duration::from_millis(10));
133 }
134
135 #[test]
136 fn test_timer_phase() {
137 let mut timer = Timer::new();
138 thread::sleep(Duration::from_millis(10));
139 timer.start_phase();
140 thread::sleep(Duration::from_millis(10));
141 assert!(timer.phase_elapsed() < timer.elapsed());
143 }
144}
145
146#[cfg(test)]
147mod tests;