diff --git a/databuild/orchestrator.rs b/databuild/orchestrator.rs index d8c1859..89a6bf2 100644 --- a/databuild/orchestrator.rs +++ b/databuild/orchestrator.rs @@ -5,7 +5,6 @@ use crate::{PartitionRef, WantDetail}; use std::collections::HashMap; use std::error::Error; use std::fmt::Debug; -use crate::build_state::BuildState; /** Orchestrator turns wants, config, and BEL state into scheduled jobs. It uses lightweight threads + @@ -69,7 +68,7 @@ impl Orchestrator { } /** Continuously invoked function to watch job run status */ - fn poll_jobs(&mut self) -> Result<(), Box> { + fn poll_job_runs(&mut self) -> Result<(), Box> { // Visit existing jobs, remove completed self.job_runs.retain_mut(|jr| { // Append emitted events @@ -146,7 +145,7 @@ impl Orchestrator { /** Entrypoint for running jobs */ pub fn join(mut self) -> Result<(), Box> { loop { - self.poll_jobs()?; + self.poll_job_runs()?; self.poll_wants()?; } } @@ -154,48 +153,106 @@ impl Orchestrator { #[cfg(test)] mod tests { - mod poll_jobs { + // The orchestrator needs to be able to actually execute job runs + mod run_jobs { + // Use case: the orchestrator should be able to execute a spawned-process job + #[test] + #[ignore] // TODO define this interface + fn test_spawned_process_job() { + todo!() + } + } + + // The orchestrator relies on polling job run status to react to job completions that imply + // key outcomes like: + // - Success: partitions produced, other job runs may be schedulable + // - Dep miss: wants need to be created + // - Failure: engineer likely needs to react + mod poll_job_runs { // Use case: we find a job that has completed, BEL should be written with appropriate event // (both for success and fail cases) #[test] + #[ignore] fn test_job_completion_events() { - // TODO + todo!() } //Use case: a job has written new stdout, it should produce a new heartbeat event in the BEL // TODO - we should come back here later and ensure we have a minimum heartbeat period #[test] + #[ignore] fn test_heartbeat_from_stdout() { - // TODO + todo!() } } + // The orchestrator polls wants so that it can react to new wants created by users, or to wants + // created by itself (for dep miss job run failures) mod poll_wants { // Use case: Empty schedulable wants is a valid case, and should create no new jobs. #[test] + #[ignore] fn test_empty_wants_noop() { - // TODO + todo!() } // Use case: Some schedulable wants with jobs that can be matched should launch those jobs // (but in this case using a noop/mock child process) #[test] + #[ignore] fn test_schedulable_wants_should_schedule() { - // TODO + todo!() } // Use case: A schedulable want that can't be matched to a job should return an error #[test] + #[ignore] fn test_schedulable_want_no_matching_job() { - // TODO + todo!() } } - mod want_group { + // Orchestrator want creation is the means of data dependency propagation, allowing the + // orchestrator to create partitions needed by jobs that produce the existing wanted partitions. + mod want_create { + // Use case: The orchestrator should map a failed job into a set of wants + #[test] + #[ignore] + fn test_job_fail_want_mapping() { + todo!() + } + } + + // Orchestrator needs to be able to achieve high level orchestration use cases. + mod orchestration { + // Use case: should run a job to produce a partition in reaction to a want, then have the + // want fulfilled. + #[test] + #[ignore] + fn test_want_builds_partition() { + todo!() + } + + // Use case: a graph with multi-hop deps should achieve the multi-hop build + // - Job B depends on part_a produced by job A + // - Job B should be attempted, fail, and create a want for part_a + // - Job A should be attempted, succeed, and produce part_a + // - Job B should be attempted, succeed, and produce part_b + #[test] + #[ignore] + fn test_multi_hop_want_builds_partition() { + todo!() + } + } + + // The orchestrator groups wants to enable efficient execution. Many individual wants may + // reference the same partitions, or many different partitions may be referenced by many + // different wants. The orchestrator needs to be able to achieve job run batching, where a + // single job run builds multiple partitions from multiple different wants. + mod want_grouping { use super::super::*; use crate::build_event_log::MemoryBELStorage; use crate::{PartitionRef, WantDetail}; - use crate::build_state::BuildState; fn create_job_config(label: &str, pattern: &str) -> JobConfiguration { JobConfiguration {