@@ -11,13 +11,14 @@ use std::time::{Duration, Instant};
1111use tokio:: sync:: mpsc:: { channel, Receiver , Sender } ;
1212
1313use anyhow:: { anyhow, bail, Result } ;
14+ use buildomat_common:: JobStream ;
1415use chrono:: prelude:: * ;
1516
1617use super :: OutputRecord ;
1718
1819fn spawn_reader < T > (
1920 tx : Sender < Activity > ,
20- name : String ,
21+ name : JobStream ,
2122 stream : Option < T > ,
2223) -> Option < std:: thread:: JoinHandle < ( ) > >
2324where
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 /*
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 ( ) ;
7680
7781#[ derive( Debug ) ]
7882pub 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 {
8589impl 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 ) ]
103107pub struct OutputDetails {
104- stream : String ,
108+ stream : JobStream ,
105109 msg : String ,
106110 time : DateTime < Utc > ,
107111}
108112
109113impl 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
132137impl 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
185214impl 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