Skip to content

Commit f2bcec5

Browse files
committed
use an enum to define job streams
1 parent 6723608 commit f2bcec5

8 files changed

Lines changed: 288 additions & 200 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ version = "0.0.0"
3636
[workspace.lints.clippy]
3737
identity_op = "allow"
3838
many_single_char_names = "allow"
39+
should_implement_trait = "allow"
3940
too_many_arguments = "allow"
4041
type_complexity = "allow"
4142
vec_init_then_push = "allow"

agent/src/exec.rs

Lines changed: 72 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ use std::time::{Duration, Instant};
1111
use tokio::sync::mpsc::{channel, Receiver, Sender};
1212

1313
use anyhow::{anyhow, bail, Result};
14+
use buildomat_common::JobStream;
1415
use chrono::prelude::*;
1516

1617
use super::OutputRecord;
1718

1819
fn spawn_reader<T>(
1920
tx: Sender<Activity>,
20-
name: String,
21+
name: JobStream,
2122
stream: Option<T>,
2223
) -> Option<std::thread::JoinHandle<()>>
2324
where
@@ -47,7 +48,10 @@ where
4748
let s = String::from_utf8_lossy(&buf);
4849

4950
if tx
50-
.blocking_send(Activity::msg(&name, s.trim_end()))
51+
.blocking_send(Activity::msg(
52+
name.clone(),
53+
s.trim_end(),
54+
))
5155
.is_err()
5256
{
5357
/*
@@ -63,7 +67,7 @@ where
6367
* server, but don't panic if we cannot.
6468
*/
6569
tx.blocking_send(Activity::msg(
66-
"error",
70+
JobStream::Error,
6771
&format!("failed to read {name}: {e:?}"),
6872
))
6973
.ok();
@@ -76,7 +80,7 @@ where
7680

7781
#[derive(Debug)]
7882
pub struct ExitDetails {
79-
stream: String,
83+
stream: JobStream,
8084
duration_ms: u64,
8185
when: DateTime<Utc>,
8286
code: i32,
@@ -85,7 +89,7 @@ pub struct ExitDetails {
8589
impl ExitDetails {
8690
pub(crate) fn to_record(&self) -> OutputRecord {
8791
OutputRecord {
88-
stream: self.stream.to_string(),
92+
stream: self.stream.clone(),
8993
msg: format!(
9094
"process exited: duration {} ms, exit code {}",
9195
self.duration_ms, self.code
@@ -101,15 +105,15 @@ impl ExitDetails {
101105

102106
#[derive(Clone, Debug)]
103107
pub struct OutputDetails {
104-
stream: String,
108+
stream: JobStream,
105109
msg: String,
106110
time: DateTime<Utc>,
107111
}
108112

109113
impl OutputDetails {
110114
pub(crate) fn to_record(&self) -> OutputRecord {
111115
OutputRecord {
112-
stream: self.stream.to_string(),
116+
stream: self.stream.clone(),
113117
msg: self.msg.to_string(),
114118
time: self.time,
115119
}
@@ -123,69 +127,94 @@ pub enum Activity {
123127
Complete,
124128
}
125129

126-
struct ActivityBuilder {
127-
error_stream: String,
128-
exit_stream: String,
129-
bgproc: Option<String>,
130+
#[derive(Clone)]
131+
pub enum ActivityBuilder {
132+
Task,
133+
Diag(String),
134+
Bg(String),
130135
}
131136

132137
impl ActivityBuilder {
133-
fn exit(&self, start: &Instant, end: &Instant, code: i32) -> Activity {
134-
Activity::Exit(ExitDetails {
135-
stream: self.exit_stream.to_string(),
136-
duration_ms: end.duration_since(*start).as_millis() as u64,
137-
when: Utc::now(),
138-
code,
139-
})
138+
fn stdout_stream(&self) -> JobStream {
139+
match self.clone() {
140+
ActivityBuilder::Task => JobStream::Stdout,
141+
ActivityBuilder::Diag(_) => JobStream::Stdout,
142+
ActivityBuilder::Bg(name) => JobStream::BgStdout { name },
143+
}
140144
}
141145

142-
fn stdout_stream(&self) -> String {
143-
if let Some(n) = &self.bgproc {
144-
format!("bg.{n}.stdout")
145-
} else {
146-
"stdout".to_string()
146+
fn stderr_stream(&self) -> JobStream {
147+
match self.clone() {
148+
ActivityBuilder::Task => JobStream::Stderr,
149+
ActivityBuilder::Diag(_) => JobStream::Stderr,
150+
ActivityBuilder::Bg(name) => JobStream::BgStderr { name },
147151
}
148152
}
149153

150-
fn stderr_stream(&self) -> String {
151-
if let Some(n) = &self.bgproc {
152-
format!("bg.{n}.stderr")
153-
} else {
154-
"stderr".to_string()
154+
fn exit_stream(&self) -> JobStream {
155+
match self.clone() {
156+
ActivityBuilder::Task => JobStream::Task,
157+
ActivityBuilder::Diag(name) => JobStream::Diag { name },
158+
ActivityBuilder::Bg(name) => JobStream::Bg { name },
155159
}
156160
}
157161

162+
fn error_stream(&self) -> JobStream {
163+
match self.clone() {
164+
ActivityBuilder::Task => JobStream::Worker,
165+
ActivityBuilder::Diag(name) => JobStream::Diag { name },
166+
ActivityBuilder::Bg(name) => JobStream::Bg { name },
167+
}
168+
}
169+
170+
fn is_bg(&self) -> bool {
171+
matches!(self, ActivityBuilder::Bg(_))
172+
}
173+
158174
fn errmsg(&self, pfx: &str, msg: &str) -> String {
159175
let mut s = format!("{pfx}: ");
160-
if let Some(bg) = &self.bgproc {
161-
s += &format!("background process {bg:?}: ");
176+
match self {
177+
ActivityBuilder::Task => {}
178+
ActivityBuilder::Diag(_) => {}
179+
ActivityBuilder::Bg(name) => {
180+
s += &format!("background process {name:?}: ")
181+
}
162182
}
163183
s += ": ";
164184
s += msg;
165185
s
166186
}
167187

188+
fn exit(&self, start: &Instant, end: &Instant, code: i32) -> Activity {
189+
Activity::Exit(ExitDetails {
190+
stream: self.exit_stream(),
191+
duration_ms: end.duration_since(*start).as_millis() as u64,
192+
when: Utc::now(),
193+
code,
194+
})
195+
}
196+
168197
fn err(&self, msg: &str) -> Activity {
169198
Activity::Output(OutputDetails {
170-
stream: self.error_stream.to_string(),
199+
stream: self.error_stream(),
171200
msg: self.errmsg("exec error", msg),
172201
time: Utc::now(),
173202
})
174203
}
175204

176205
fn warn(&self, msg: &str) -> Activity {
177206
Activity::Output(OutputDetails {
178-
stream: self.error_stream.to_string(),
207+
stream: self.error_stream(),
179208
msg: self.errmsg("exec warning", msg),
180209
time: Utc::now(),
181210
})
182211
}
183212
}
184213

185214
impl Activity {
186-
fn msg(stream: &str, msg: &str) -> Activity {
215+
fn msg(stream: JobStream, msg: &str) -> Activity {
187216
Activity::Output(OutputDetails {
188-
stream: stream.to_string(),
217+
stream,
189218
msg: msg.to_string(),
190219
time: Utc::now(),
191220
})
@@ -229,39 +258,13 @@ pub fn thread_done(
229258
}
230259
}
231260

232-
pub fn run_diagnostic(cmd: Command, name: &str) -> Result<Receiver<Activity>> {
233-
let (tx, rx) = channel::<Activity>(100);
234-
235-
run_common(
236-
cmd,
237-
ActivityBuilder {
238-
error_stream: format!("diag.{name}"),
239-
exit_stream: format!("diag.{name}"),
240-
bgproc: None,
241-
},
242-
tx,
243-
)?;
244-
245-
Ok(rx)
246-
}
247-
248-
pub fn run(cmd: Command) -> Result<Receiver<Activity>> {
261+
pub fn run(cmd: Command, ab: ActivityBuilder) -> Result<Receiver<Activity>> {
249262
let (tx, rx) = channel::<Activity>(100);
250-
251-
run_common(
252-
cmd,
253-
ActivityBuilder {
254-
error_stream: "worker".to_string(),
255-
exit_stream: "task".to_string(),
256-
bgproc: None,
257-
},
258-
tx,
259-
)?;
260-
263+
run_inner(cmd, ab, tx)?;
261264
Ok(rx)
262265
}
263266

264-
fn run_common(
267+
fn run_inner(
265268
mut cmd: Command,
266269
ab: ActivityBuilder,
267270
tx: Sender<Activity>,
@@ -289,7 +292,7 @@ fn run_common(
289292
)
290293
.unwrap();
291294

292-
if ab.bgproc.is_some() {
295+
if ab.is_bg() {
293296
/*
294297
* No further notifications are required for background
295298
* processes.
@@ -313,7 +316,7 @@ fn run_common(
313316
let stdio_warning = !thread_done(&mut readout, "stdout", until)
314317
| !thread_done(&mut readerr, "stderr", until);
315318

316-
if ab.bgproc.is_some() {
319+
if ab.is_bg() {
317320
/*
318321
* No further notifications are required for background
319322
* processes.
@@ -333,7 +336,7 @@ fn run_common(
333336
}
334337
};
335338

336-
assert!(ab.bgproc.is_none());
339+
assert!(!ab.is_bg());
337340

338341
if stdio_warning {
339342
tx.blocking_send(ab.warn(
@@ -449,13 +452,9 @@ impl BackgroundProcesses {
449452
c.uid(uid);
450453
c.gid(gid);
451454

452-
let pid = run_common(
455+
let pid = run_inner(
453456
c,
454-
ActivityBuilder {
455-
error_stream: format!("bg.{name}"),
456-
exit_stream: format!("bg.{name}"),
457-
bgproc: Some(name.to_string()),
458-
},
457+
ActivityBuilder::Bg(name.to_string()),
459458
self.tx.clone(),
460459
)
461460
.map_err(|e| anyhow!("starting background process {name:?}: {e}"))?;
@@ -522,8 +521,7 @@ impl BackgroundProcesses {
522521
self.rx.close();
523522
while let Some(a) = self.rx.recv().await {
524523
if let Activity::Output(o) = &a {
525-
if o.stream.ends_with("stdout") || o.stream.ends_with("stderr")
526-
{
524+
if o.stream.is_output() {
527525
lastwords.push(a);
528526
}
529527
}

0 commit comments

Comments
 (0)