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