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