ant_service_management/
registry.rs1use crate::error::{Error, Result};
10use crate::{DaemonServiceData, NatDetectionStatus, NodeServiceData};
11use serde::{Deserialize, Serialize};
12use std::sync::Arc;
13use std::{
14 io::{Read, Write},
15 path::{Path, PathBuf},
16};
17use tokio::sync::RwLock;
18
19#[derive(Clone, Debug)]
23#[allow(clippy::type_complexity)]
24pub struct NodeRegistryManager {
25 pub daemon: Arc<RwLock<Option<Arc<RwLock<DaemonServiceData>>>>>,
26 pub environment_variables: Arc<RwLock<Option<Vec<(String, String)>>>>,
27 pub nat_status: Arc<RwLock<Option<NatDetectionStatus>>>,
28 pub nodes: Arc<RwLock<Vec<Arc<RwLock<NodeServiceData>>>>>,
29 pub save_path: PathBuf,
30}
31
32impl From<NodeRegistry> for NodeRegistryManager {
33 fn from(registry: NodeRegistry) -> Self {
34 NodeRegistryManager {
35 daemon: Arc::new(RwLock::new(
36 registry.daemon.map(|daemon| Arc::new(RwLock::new(daemon))),
37 )),
38 environment_variables: Arc::new(RwLock::new(registry.environment_variables)),
39 nat_status: Arc::new(RwLock::new(registry.nat_status)),
40 nodes: Arc::new(RwLock::new(
41 registry
42 .nodes
43 .into_iter()
44 .map(|node| Arc::new(RwLock::new(node)))
45 .collect(),
46 )),
47 save_path: registry.save_path,
48 }
49 }
50}
51
52impl NodeRegistryManager {
53 pub fn empty(save_path: PathBuf) -> Self {
57 NodeRegistryManager {
58 daemon: Arc::new(RwLock::new(None)),
59 environment_variables: Arc::new(RwLock::new(None)),
60 nat_status: Arc::new(RwLock::new(None)),
61 nodes: Arc::new(RwLock::new(Vec::new())),
62 save_path,
63 }
64 }
65
66 #[allow(clippy::unused_async)]
69 pub async fn load(path: &Path) -> Result<Self> {
70 let registry = NodeRegistry::load(path)?;
71 let manager = NodeRegistryManager::from(registry);
72
73 Ok(manager)
74 }
75
76 pub async fn save(&self) -> Result<()> {
78 let registry = self.to_registry().await;
79 registry.save()?;
80 Ok(())
81 }
82
83 async fn to_registry(&self) -> NodeRegistry {
85 let nodes = self.get_node_service_data().await;
86 let mut daemon = None;
87 {
88 if let Some(d) = self.daemon.read().await.as_ref() {
89 daemon = Some(d.read().await.clone());
90 }
91 }
92 NodeRegistry {
93 daemon,
94 environment_variables: self.environment_variables.read().await.clone(),
95 nat_status: self.nat_status.read().await.clone(),
96 nodes,
97 save_path: self.save_path.clone(),
98 }
99 }
100
101 pub async fn to_status_summary(&self) -> StatusSummary {
103 let registry = self.to_registry().await;
104 registry.to_status_summary()
105 }
106
107 pub async fn push_node(&self, node: NodeServiceData) {
109 let mut nodes = self.nodes.write().await;
110 nodes.push(Arc::new(RwLock::new(node)));
111 }
112
113 pub async fn insert_daemon(&self, daemon: DaemonServiceData) {
115 let mut daemon_lock = self.daemon.write().await;
116 *daemon_lock = Some(Arc::new(RwLock::new(daemon)));
117 }
118
119 pub async fn get_node_service_data(&self) -> Vec<NodeServiceData> {
120 let mut node_services = Vec::new();
121 for node in self.nodes.read().await.iter() {
122 let node = node.read().await;
123 node_services.push(node.clone());
124 }
125 node_services
126 }
127}
128
129#[derive(Clone, Debug, Serialize, Deserialize)]
131struct NodeRegistry {
132 daemon: Option<DaemonServiceData>,
133 environment_variables: Option<Vec<(String, String)>>,
134 nat_status: Option<NatDetectionStatus>,
135 nodes: Vec<NodeServiceData>,
136 save_path: PathBuf,
137}
138
139#[derive(Clone, Debug, Serialize, Deserialize)]
140pub struct StatusSummary {
141 pub nodes: Vec<NodeServiceData>,
142 pub daemon: Option<DaemonServiceData>,
143}
144
145impl NodeRegistry {
146 fn save(&self) -> Result<()> {
147 debug!(
148 "Saving node registry to {}",
149 self.save_path.to_string_lossy()
150 );
151 let path = Path::new(&self.save_path);
152 if let Some(parent) = path.parent() {
153 std::fs::create_dir_all(parent).inspect_err(|err| {
154 error!("Error creating node registry parent {parent:?}: {err:?}")
155 })?;
156 }
157
158 let json = serde_json::to_string(self)?;
159 let mut file = std::fs::File::create(self.save_path.clone())
160 .inspect_err(|err| error!("Error creating node registry file: {err:?}"))?;
161 file.write_all(json.as_bytes())
162 .inspect_err(|err| error!("Error writing to node registry: {err:?}"))?;
163
164 Ok(())
165 }
166
167 fn load(path: &Path) -> Result<Self> {
168 if !path.exists() {
169 debug!("Loading default node registry as {path:?} does not exist");
170 return Ok(NodeRegistry {
171 daemon: None,
172 environment_variables: None,
173 nat_status: None,
174 nodes: vec![],
175 save_path: path.to_path_buf(),
176 });
177 }
178 debug!("Loading node registry from {}", path.to_string_lossy());
179
180 let mut file = std::fs::File::open(path)
181 .inspect_err(|err| error!("Error opening node registry: {err:?}"))?;
182
183 let mut contents = String::new();
184 file.read_to_string(&mut contents)
185 .inspect_err(|err| error!("Error reading node registry: {err:?}"))?;
186
187 if contents.is_empty() {
190 return Ok(NodeRegistry {
191 daemon: None,
192 environment_variables: None,
193 nat_status: None,
194 nodes: vec![],
195 save_path: path.to_path_buf(),
196 });
197 }
198
199 Self::from_json(&contents)
200 }
201
202 fn from_json(json: &str) -> Result<Self> {
203 let registry = serde_json::from_str(json)
204 .inspect_err(|err| error!("Error deserializing node registry: {err:?}"))?;
205 Ok(registry)
206 }
207
208 fn to_status_summary(&self) -> StatusSummary {
209 StatusSummary {
210 nodes: self.nodes.clone(),
211 daemon: self.daemon.clone(),
212 }
213 }
214}
215
216pub fn get_local_node_registry_path() -> Result<PathBuf> {
217 let path = dirs_next::data_dir()
218 .ok_or_else(|| {
219 error!("Failed to get data_dir");
220 Error::UserDataDirectoryNotObtainable
221 })?
222 .join("autonomi")
223 .join("local_node_registry.json");
224 if let Some(parent) = path.parent() {
225 std::fs::create_dir_all(parent)
226 .inspect_err(|err| error!("Error creating node registry parent {parent:?}: {err:?}"))?;
227 }
228 Ok(path)
229}