diff --git a/databuild/job_run.rs b/databuild/job_run.rs index 88c9c43..01adeeb 100644 --- a/databuild/job_run.rs +++ b/databuild/job_run.rs @@ -1,9 +1,9 @@ use crate::build_event_log::{BELStorage, MemoryBELStorage}; use crate::data_build_event::Event; -use crate::JobRunStatus; +use crate::{JobRunHeartbeatEventV1, JobRunStatus}; use std::error::Error; use std::io::BufRead; -use std::process::Child; +use std::process::{Child, Command, Stdio}; use uuid::Uuid; // TODO log to /var/log/databuild/jobruns/$JOB_RUN_ID/, and rotate over max size (e.g. only ever use 1GB for logs) @@ -11,8 +11,12 @@ use uuid::Uuid; pub trait JobRun { fn id(&self) -> Uuid; + /** + Visit is responsible for observing the state of the job run, + */ fn visit(&mut self) -> Result>; fn cancel(&mut self) -> Result<(), Box>; + fn run(&mut self) -> Result>; } pub enum JobRunConfig { @@ -28,8 +32,11 @@ pub fn spawn_job_run(config: JobRunConfig) -> Result, Box, pub storage: MemoryBELStorage, + pub running: bool, + pub entry_point: String, + pub args: Vec, } impl JobRun for SubProcessJobRun { @@ -44,11 +51,28 @@ impl JobRun for SubProcessJobRun { fn cancel(&mut self) -> Result<(), Box> { todo!() } + + fn run(&mut self) -> Result> { + self.process = Some(Command::new(self.entry_point.clone()) + .args(self.args.clone()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?); + self.running = true; + Ok(JobRunHeartbeatEventV1 { job_run_id: self.id().to_string() }) + } } impl SubProcessJobRun { pub fn spawn(entry_point: String, args: Vec) -> Result, Box> { - todo!() + Ok(Box::new(SubProcessJobRun { + job_run_id: Uuid::new_v4(), + process: None, + storage: MemoryBELStorage::default(), + running: false, + entry_point, + args, + })) } } @@ -58,5 +82,36 @@ pub struct JobRunPollResult { } mod tests { + /// Happy path - run that succeeds should emit a JobRunSuccessEventV1 + #[test] + fn test_job_run_success_returns_job_run_success_event() { + todo!() + } + /// Job that runs for more than 1 heartbeat interval should emit a JobRunHeartbeatEventV1 event + #[test] + fn test_running_job_run_poll_returns_heartbeat() { + todo!() + } + + /// Job run that fails should emit a JobRunFailureEventV1 + #[test] + fn test_job_run_failure_returns_job_run_failure_event() { + todo!() + } + + /// Canceling an event before it completes should result in it: + /// - Stop the actual subprocess (e.g. no output file should be written) + /// - Emitting a JobRunCancelEventV1 event + #[test] + fn test_job_run_cancel_returns_job_run_cancel_event() { + todo!() + } + + /// Job run that fails and emits a recognized "dep miss" statement should emit a JobRunMissingDepsEventV1 + #[test] + #[ignore] + fn test_job_run_fail_on_missing_deps_should_emit_missing_deps_event() { + todo!() + } }