tatara_engine/domain/
store_adapter.rs1use anyhow::Result;
9use std::collections::HashMap;
10use std::sync::Arc;
11use uuid::Uuid;
12
13use crate::cluster::store::ClusterStore;
14use tatara_core::cluster::types::NodeMeta;
15use tatara_core::domain::allocation::Allocation;
16use tatara_core::domain::job::{Job, JobStatus};
17use tatara_core::domain::node::{Node, NodeStatus};
18
19pub struct ClusterStoreAdapter {
21 store: Arc<ClusterStore>,
22}
23
24impl ClusterStoreAdapter {
25 pub fn new(store: Arc<ClusterStore>) -> Self {
26 Self { store }
27 }
28
29 pub async fn list_jobs(&self) -> Vec<Job> {
31 self.store.list_jobs().await
32 }
33
34 pub async fn list_nodes(&self) -> Vec<Node> {
36 self.store
37 .list_nodes()
38 .await
39 .into_iter()
40 .map(node_meta_to_node)
41 .collect()
42 }
43
44 pub async fn scheduling_generation(&self) -> u64 {
46 let state = self.store.state().await;
47 state.scheduling_generation
48 }
49
50 pub async fn put_job(&self, job: Job) -> Result<()> {
52 self.store.put_job(job).await?;
53 Ok(())
54 }
55
56 pub async fn update_job_status(&self, job_id: &str, status: JobStatus) -> Result<()> {
58 self.store.update_job_status(job_id, status).await?;
59 Ok(())
60 }
61
62 pub async fn put_allocation(&self, alloc: Allocation) -> Result<()> {
64 self.store.put_allocation(alloc).await?;
65 Ok(())
66 }
67
68 pub async fn is_leader(&self) -> bool {
70 self.store.is_leader().await
71 }
72}
73
74fn node_meta_to_node(meta: NodeMeta) -> Node {
76 let mut attributes = HashMap::new();
77 attributes.insert("os".to_string(), meta.os.clone());
78 attributes.insert("arch".to_string(), meta.arch.clone());
79 attributes.insert("hostname".to_string(), meta.hostname.clone());
80
81 Node {
82 id: format!("{}", meta.node_id),
83 address: meta.http_addr.clone(),
84 status: if meta.eligible {
85 NodeStatus::Ready
86 } else {
87 NodeStatus::Draining
88 },
89 eligible: meta.eligible,
90 total_resources: meta.total_resources,
91 available_resources: meta.available_resources,
92 attributes,
93 drivers: meta.drivers,
94 last_heartbeat: meta.joined_at,
95 allocations: Vec::new(),
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use chrono::Utc;
103 use tatara_core::cluster::types::NodeRoles;
104 use tatara_core::domain::job::Resources;
105
106 #[test]
107 fn test_node_meta_conversion() {
108 let meta = NodeMeta {
109 node_id: 42,
110 hostname: "test-host".to_string(),
111 http_addr: "127.0.0.1:4646".to_string(),
112 gossip_addr: "127.0.0.1:5679".to_string(),
113 raft_addr: "127.0.0.1:4649".to_string(),
114 os: "darwin".to_string(),
115 arch: "aarch64".to_string(),
116 roles: NodeRoles::default(),
117 drivers: vec![],
118 total_resources: Resources {
119 cpu_mhz: 4000,
120 memory_mb: 8192,
121 },
122 available_resources: Resources {
123 cpu_mhz: 3000,
124 memory_mb: 6144,
125 },
126 allocations_running: 2,
127 joined_at: Utc::now(),
128 version: "0.2.0".to_string(),
129 eligible: true,
130 wireguard_pubkey: None,
131 tunnel_address: None,
132 };
133
134 let node = node_meta_to_node(meta);
135 assert_eq!(node.id, "42");
136 assert_eq!(node.status, NodeStatus::Ready);
137 assert!(node.eligible);
138 assert_eq!(node.attributes["arch"], "aarch64");
139 assert_eq!(node.total_resources.cpu_mhz, 4000);
140 }
141}