use serde::Serialize;
use crate::def::{DefError, DependencyGraph, Node, StackDef};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum StepKind {
ProvisionIntegration,
Materialize,
Setup,
Prepare,
Start,
HealthGate,
}
impl StepKind {
fn id_prefix(self) -> &'static str {
match self {
Self::ProvisionIntegration => "integration",
Self::Materialize => "materialize",
Self::Setup => "setup",
Self::Prepare => "prepare",
Self::Start => "start",
Self::HealthGate => "health",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Step {
pub id: String,
pub kind: StepKind,
pub node: String,
}
impl Step {
fn new(kind: StepKind, node: &str) -> Self {
Self {
id: format!("{}:{node}", kind.id_prefix()),
kind,
node: node.to_owned(),
}
}
}
impl StackDef {
pub fn plan(&self) -> Result<Vec<Step>, DefError> {
let graph = DependencyGraph::derive(self)?;
let mut steps = Vec::new();
for node in graph.startup_order() {
match node {
Node::Integration(name) => {
steps.push(Step::new(StepKind::ProvisionIntegration, name));
}
Node::Service(name) => {
let Some(service) = self.services.get(name) else {
continue;
};
steps.push(Step::new(StepKind::Materialize, name));
if service.setup.is_some() {
steps.push(Step::new(StepKind::Setup, name));
}
if service.prepare.is_some() {
steps.push(Step::new(StepKind::Prepare, name));
}
steps.push(Step::new(StepKind::Start, name));
steps.push(Step::new(StepKind::HealthGate, name));
}
}
}
Ok(steps)
}
}