Skip to main content

floe_core/run/
mod.rs

1use std::collections::HashMap;
2use std::path::Path;
3
4use crate::{config, ConfigError, FloeResult, RunOptions, ValidateOptions};
5
6mod context;
7pub(crate) mod entity;
8mod file;
9pub(crate) mod normalize;
10mod output;
11mod reporting;
12
13use context::RunContext;
14use entity::{run_entity, EntityRunResult};
15
16pub(super) const MAX_RESOLVED_INPUTS: usize = 50;
17
18#[derive(Debug, Clone)]
19pub struct RunOutcome {
20    pub run_id: String,
21    pub report_base_path: String,
22    pub entity_outcomes: Vec<EntityOutcome>,
23}
24
25#[derive(Debug, Clone)]
26pub struct EntityOutcome {
27    pub report: crate::report::RunReport,
28    pub file_timings_ms: Vec<Option<u64>>,
29}
30
31pub(crate) fn validate_entities(
32    config: &config::RootConfig,
33    selected: &[String],
34) -> FloeResult<()> {
35    let missing: Vec<String> = selected
36        .iter()
37        .filter(|name| !config.entities.iter().any(|entity| &entity.name == *name))
38        .cloned()
39        .collect();
40
41    if !missing.is_empty() {
42        return Err(Box::new(ConfigError(format!(
43            "entities not found: {}",
44            missing.join(", ")
45        ))));
46    }
47    Ok(())
48}
49
50pub fn run(config_path: &Path, options: RunOptions) -> FloeResult<RunOutcome> {
51    let validate_options = ValidateOptions {
52        entities: options.entities.clone(),
53    };
54    crate::validate(config_path, validate_options)?;
55
56    let context = RunContext::new(config_path, &options)?;
57    if !options.entities.is_empty() {
58        validate_entities(&context.config, &options.entities)?;
59    }
60
61    let mut entity_outcomes = Vec::new();
62    let mut abort_run = false;
63    let mut s3_clients = HashMap::new();
64    for entity in &context.config.entities {
65        let EntityRunResult {
66            outcome,
67            abort_run: aborted,
68        } = run_entity(&context, &mut s3_clients, entity)?;
69        entity_outcomes.push(outcome);
70        abort_run = abort_run || aborted;
71        if abort_run {
72            break;
73        }
74    }
75
76    Ok(RunOutcome {
77        run_id: context.run_id.clone(),
78        report_base_path: context.report_base_path.clone(),
79        entity_outcomes,
80    })
81}