Skip to main content

max / makenotwork

2.0 KB · 54 lines History Blame Raw
1 use crate::config::Config;
2 use crate::domain::NodeId;
3 use crate::events::EventTx;
4 use crate::topology::{Node, Topology};
5 use metrics_exporter_prometheus::PrometheusHandle;
6 use ops_exec::{CapabilitySet, Executor, LocalExec, SshExec};
7 use sqlx::SqlitePool;
8 use std::collections::HashMap;
9 use std::sync::Arc;
10 use tokio::sync::Mutex;
11 use tokio::task::AbortHandle;
12
13 /// Per-node executors keyed by node id, built once from the topology at
14 /// startup. The deploy path looks a node's executor up here instead of
15 /// constructing ssh/rsync invocations inline.
16 pub type ExecutorMap = HashMap<NodeId, Arc<dyn Executor>>;
17
18 #[derive(Clone)]
19 pub struct AppState {
20 pub pool: SqlitePool,
21 pub topo: Arc<Topology>,
22 pub cfg: Arc<Config>,
23 pub prom: PrometheusHandle,
24 /// Single-slot guard for the build pipeline. A new /rebuild aborts any
25 /// in-flight build (cargo + gates) so the latest push always wins.
26 pub active_build: Arc<Mutex<Option<AbortHandle>>>,
27 /// Broadcast bus for live operator events. WS /events subscribes; all
28 /// build/gate/deploy code sites emit on this.
29 pub events: EventTx,
30 /// One capability-scoped [`Executor`] per node, built from the topology.
31 pub executors: Arc<ExecutorMap>,
32 }
33
34 /// Build the executor for one node: a `LocalExec` for the `local` fast-path, an
35 /// `SshExec` otherwise, each granted the node's declared capabilities (which
36 /// default to deploy+restart / observe health — the historical behavior).
37 pub fn build_executor(node: &Node) -> Arc<dyn Executor> {
38 let caps = CapabilitySet::from_tokens(&node.actuate, &node.observe);
39 if node.ssh_target == "local" || node.ssh_target.is_empty() {
40 Arc::new(LocalExec::new(caps))
41 } else {
42 Arc::new(SshExec::new(node.ssh_target.clone(), caps))
43 }
44 }
45
46 /// Build the full node → executor map from every tier's nodes.
47 pub fn build_executors(topo: &Topology) -> ExecutorMap {
48 topo.tiers
49 .iter()
50 .flat_map(|t| t.nodes.iter())
51 .map(|node| (node.name.clone(), build_executor(node)))
52 .collect()
53 }
54