stackless_core/engine/
plan.rs1use serde::Serialize;
6
7use crate::def::{DefError, DependencyGraph, Node, StackDef};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
10#[serde(rename_all = "snake_case")]
11pub enum StepKind {
12 ProvisionIntegration,
14 Materialize,
16 Setup,
18 Prepare,
20 Start,
22 HealthGate,
24}
25
26impl StepKind {
27 fn id_prefix(self) -> &'static str {
28 match self {
29 Self::ProvisionIntegration => "integration",
30 Self::Materialize => "materialize",
31 Self::Setup => "setup",
32 Self::Prepare => "prepare",
33 Self::Start => "start",
34 Self::HealthGate => "health",
35 }
36 }
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
40pub struct Step {
41 pub id: String,
43 pub kind: StepKind,
44 pub node: String,
46}
47
48impl Step {
49 fn new(kind: StepKind, node: &str) -> Self {
50 Self {
51 id: format!("{}:{node}", kind.id_prefix()),
52 kind,
53 node: node.to_owned(),
54 }
55 }
56}
57
58impl StackDef {
59 pub fn plan(&self) -> Result<Vec<Step>, DefError> {
61 let graph = DependencyGraph::derive(self)?;
62 let mut steps = Vec::new();
63 for node in graph.startup_order() {
64 match node {
65 Node::Integration(name) => {
66 steps.push(Step::new(StepKind::ProvisionIntegration, name));
67 }
68 Node::Service(name) => {
69 let Some(service) = self.services.get(name) else {
70 continue;
71 };
72 steps.push(Step::new(StepKind::Materialize, name));
73 if service.setup.is_some() {
74 steps.push(Step::new(StepKind::Setup, name));
75 }
76 if service.prepare.is_some() {
77 steps.push(Step::new(StepKind::Prepare, name));
78 }
79 steps.push(Step::new(StepKind::Start, name));
80 steps.push(Step::new(StepKind::HealthGate, name));
81 }
82 }
83 }
84 Ok(steps)
85 }
86}