use super::{EventBufferStepData, StepKey, StepStatus};
use crate::{events::ExecutionUuid, spec::EngineSpec};
use std::{fmt, time::Duration};
#[derive(Clone, Debug)]
pub struct ExecutionSummary {
pub total_steps: usize,
pub execution_status: ExecutionStatus,
}
impl ExecutionSummary {
pub(super) fn new<S: EngineSpec>(
execution_id: ExecutionUuid,
steps: &[&EventBufferStepData<S>],
) -> Self {
let total_steps = steps.len();
let mut execution_status = ExecutionStatus::NotStarted;
for data in steps {
let step_key =
StepKey { execution_id, index: data.step_info().index };
match data.step_status() {
StepStatus::NotStarted => {
}
StepStatus::Running { low_priority, progress_event } => {
let root_total_elapsed = low_priority
.iter()
.map(|event| event.total_elapsed)
.chain(std::iter::once(progress_event.total_elapsed))
.max()
.expect("at least one value was provided");
execution_status = ExecutionStatus::Running {
step_key,
root_total_elapsed,
};
}
StepStatus::Completed { reason } => {
let (root_total_elapsed, leaf_total_elapsed) =
match reason.step_completed_info() {
Some(info) => (
Some(info.root_total_elapsed),
Some(info.leaf_total_elapsed),
),
None => (None, None),
};
let terminal_status = ExecutionTerminalInfo {
kind: TerminalKind::Completed,
root_total_elapsed,
leaf_total_elapsed,
step_key,
};
execution_status =
ExecutionStatus::Terminal(terminal_status);
}
StepStatus::Failed { reason } => {
let (root_total_elapsed, leaf_total_elapsed) =
match reason.step_failed_info() {
Some(info) => (
Some(info.root_total_elapsed),
Some(info.leaf_total_elapsed),
),
None => (None, None),
};
let terminal_status = ExecutionTerminalInfo {
kind: TerminalKind::Failed,
root_total_elapsed,
leaf_total_elapsed,
step_key,
};
execution_status =
ExecutionStatus::Terminal(terminal_status);
}
StepStatus::Aborted { reason, .. } => {
let (root_total_elapsed, leaf_total_elapsed) =
match reason.step_aborted_info() {
Some(info) => (
Some(info.root_total_elapsed),
Some(info.leaf_total_elapsed),
),
None => (None, None),
};
let terminal_status = ExecutionTerminalInfo {
kind: TerminalKind::Aborted,
root_total_elapsed,
leaf_total_elapsed,
step_key,
};
execution_status =
ExecutionStatus::Terminal(terminal_status);
}
StepStatus::WillNotBeRun { .. } => {
}
};
}
Self { total_steps, execution_status }
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ExecutionStatus {
NotStarted,
Running {
step_key: StepKey,
root_total_elapsed: Duration,
},
Terminal(ExecutionTerminalInfo),
}
impl ExecutionStatus {
pub fn terminal_info(&self) -> Option<&ExecutionTerminalInfo> {
match self {
Self::NotStarted | Self::Running { .. } => None,
Self::Terminal(info) => Some(info),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ExecutionTerminalInfo {
pub kind: TerminalKind,
pub root_total_elapsed: Option<Duration>,
pub leaf_total_elapsed: Option<Duration>,
pub step_key: StepKey,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TerminalKind {
Completed,
Failed,
Aborted,
}
impl fmt::Display for TerminalKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Completed => write!(f, "completed"),
Self::Failed => write!(f, "failed"),
Self::Aborted => write!(f, "aborted"),
}
}
}