Mountain/Environment/
StorageProvider.rs1#![allow(non_snake_case, non_camel_case_types)]
15
16use std::{collections::HashMap, path::PathBuf};
17
18use Common::{Error::CommonError::CommonError, Storage::StorageProvider::StorageProvider};
19use async_trait::async_trait;
20use log::{error, info, trace};
21use serde_json::Value;
22use tokio::fs;
23
24use super::{MountainEnvironment::MountainEnvironment, Utility};
25
26#[async_trait]
27impl StorageProvider for MountainEnvironment {
28 async fn GetStorageValue(&self, IsGlobalScope:bool, Key:&str) -> Result<Option<Value>, CommonError> {
30 let ScopeName = if IsGlobalScope { "Global" } else { "WorkSpace" };
31
32 trace!("[StorageProvider] Getting value from {} scope for key: {}", ScopeName, Key);
33
34 let StorageMapMutex = if IsGlobalScope {
35 &self.ApplicationState.GlobalMemento
36 } else {
37 &self.ApplicationState.WorkSpaceMemento
38 };
39
40 let StorageMapGuard = StorageMapMutex
41 .lock()
42 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
43
44 Ok(StorageMapGuard.get(Key).cloned())
45 }
46
47 async fn UpdateStorageValue(
49 &self,
50
51 IsGlobalScope:bool,
52
53 Key:String,
54
55 ValueToSet:Option<Value>,
56 ) -> Result<(), CommonError> {
57 let ScopeName = if IsGlobalScope { "Global" } else { "WorkSpace" };
58
59 info!("[StorageProvider] Updating value in {} scope for key: {}", ScopeName, Key);
60
61 let (StorageMapMutex, StoragePathOption) = if IsGlobalScope {
62 (
63 self.ApplicationState.GlobalMemento.clone(),
64 Some(self.ApplicationState.GlobalMementoPath.clone()),
65 )
66 } else {
67 (
68 self.ApplicationState.WorkSpaceMemento.clone(),
69 self.ApplicationState
70 .WorkSpaceMementoPath
71 .lock()
72 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
73 .clone(),
74 )
75 };
76
77 let DataToSave = {
79 let mut StorageMapGuard = StorageMapMutex
80 .lock()
81 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
82
83 if let Some(Value) = ValueToSet {
84 StorageMapGuard.insert(Key, Value);
85 } else {
86 StorageMapGuard.remove(&Key);
87 }
88
89 StorageMapGuard.clone()
90 };
91
92 if let Some(StoragePath) = StoragePathOption {
93 tokio::spawn(async move {
94 SaveStorageToDisk(StoragePath, DataToSave).await;
95 });
96 }
97
98 Ok(())
99 }
100
101 async fn GetAllStorage(&self, IsGlobalScope:bool) -> Result<Value, CommonError> {
103 let ScopeName = if IsGlobalScope { "Global" } else { "WorkSpace" };
104
105 trace!("[StorageProvider] Getting all values from {} scope.", ScopeName);
106
107 let StorageMapMutex = if IsGlobalScope {
108 &self.ApplicationState.GlobalMemento
109 } else {
110 &self.ApplicationState.WorkSpaceMemento
111 };
112
113 let StorageMapGuard = StorageMapMutex
114 .lock()
115 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
116
117 Ok(serde_json::to_value(&*StorageMapGuard)?)
118 }
119
120 async fn SetAllStorage(&self, IsGlobalScope:bool, FullState:Value) -> Result<(), CommonError> {
122 let ScopeName = if IsGlobalScope { "Global" } else { "WorkSpace" };
123
124 info!("[StorageProvider] Setting all values for {} scope.", ScopeName);
125
126 let DeserializedState:HashMap<String, Value> = serde_json::from_value(FullState)?;
127
128 let (StorageMapMutex, StoragePathOption) = if IsGlobalScope {
129 (
130 self.ApplicationState.GlobalMemento.clone(),
131 Some(self.ApplicationState.GlobalMementoPath.clone()),
132 )
133 } else {
134 (
135 self.ApplicationState.WorkSpaceMemento.clone(),
136 self.ApplicationState
137 .WorkSpaceMementoPath
138 .lock()
139 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
140 .clone(),
141 )
142 };
143
144 *StorageMapMutex
146 .lock()
147 .map_err(Utility::MapApplicationStateLockErrorToCommonError)? = DeserializedState.clone();
148
149 if let Some(StoragePath) = StoragePathOption {
151 tokio::spawn(async move {
152 SaveStorageToDisk(StoragePath, DeserializedState).await;
153 });
154 }
155
156 Ok(())
157 }
158}
159
160async fn SaveStorageToDisk(Path:PathBuf, Data:HashMap<String, Value>) {
165 trace!("[StorageProvider] Persisting storage to disk: {}", Path.display());
166
167 match serde_json::to_string_pretty(&Data) {
168 Ok(JSONString) => {
169 if let Some(ParentDirectory) = Path.parent() {
170 if let Err(Error) = fs::create_dir_all(ParentDirectory).await {
171 error!(
172 "[StorageProvider] Failed to create parent directory for '{}': {}",
173 Path.display(),
174 Error
175 );
176
177 return;
178 }
179 }
180
181 if let Err(Error) = fs::write(&Path, JSONString).await {
182 error!(
183 "[StorageProvider] Failed to write storage file to '{}': {}",
184 Path.display(),
185 Error
186 );
187 }
188 },
189
190 Err(Error) => {
191 error!(
192 "[StorageProvider] Failed to serialize storage data for '{}': {}",
193 Path.display(),
194 Error
195 );
196 },
197 }
198}