reactive_graph_config_impl/
config_manager_impl.rs

1use std::path::PathBuf;
2use std::sync::RwLock;
3
4use async_trait::async_trait;
5use log::debug;
6use log::error;
7use log::info;
8use springtime_di::Component;
9use springtime_di::component_alias;
10
11use reactive_graph_config_api::ConfigManager;
12use reactive_graph_config_model::GraphQLServerConfig;
13use reactive_graph_config_model::InstanceConfig;
14use reactive_graph_config_model::PluginsConfig;
15use reactive_graph_config_model::RemotesConfig;
16use reactive_graph_lifecycle::Lifecycle;
17
18const DEFAULT_CONFIG_LOCATION: &str = "./config";
19
20const DEFAULT_INSTANCE_CONFIG_FILENAME: &str = "instance.toml";
21
22const DEFAULT_GRAPHQL_CONFIG_FILENAME: &str = "graphql.toml";
23
24const DEFAULT_PLUGINS_CONFIG_FILENAME: &str = "plugins.toml";
25
26const DEFAULT_REMOTES_CONFIG_FILENAME: &str = "remotes.toml";
27
28fn create_instance_config_location() -> RwLock<PathBuf> {
29    // InstanceConfigLocation {
30    let mut p = PathBuf::from(DEFAULT_CONFIG_LOCATION);
31    p.push(DEFAULT_INSTANCE_CONFIG_FILENAME);
32    RwLock::new(p)
33}
34
35fn create_graphql_server_config_location() -> RwLock<PathBuf> {
36    let mut p = PathBuf::from(DEFAULT_CONFIG_LOCATION);
37    p.push(DEFAULT_GRAPHQL_CONFIG_FILENAME);
38    RwLock::new(p)
39}
40
41fn create_plugins_config_location() -> RwLock<PathBuf> {
42    let mut p = PathBuf::from(DEFAULT_CONFIG_LOCATION);
43    p.push(DEFAULT_PLUGINS_CONFIG_FILENAME);
44    RwLock::new(p)
45}
46
47fn create_remotes_config_location() -> RwLock<PathBuf> {
48    let mut p = PathBuf::from(DEFAULT_CONFIG_LOCATION);
49    p.push(DEFAULT_REMOTES_CONFIG_FILENAME);
50    RwLock::new(p)
51}
52
53fn create_instance_config() -> RwLock<InstanceConfig> {
54    RwLock::new(InstanceConfig::default())
55}
56
57fn create_graphql_server_config() -> RwLock<GraphQLServerConfig> {
58    RwLock::new(GraphQLServerConfig::default())
59}
60
61fn create_plugins_config() -> RwLock<PluginsConfig> {
62    RwLock::new(PluginsConfig::default())
63}
64
65fn create_remotes_config() -> RwLock<RemotesConfig> {
66    RwLock::new(RemotesConfig::default())
67}
68
69#[derive(Component)]
70pub struct ConfigManagerImpl {
71    #[component(default = "create_instance_config_location")]
72    instance_config_location: RwLock<PathBuf>,
73    #[component(default = "create_graphql_server_config_location")]
74    graphql_server_config_location: RwLock<PathBuf>,
75    #[component(default = "create_plugins_config_location")]
76    plugins_config_location: RwLock<PathBuf>,
77    #[component(default = "create_remotes_config_location")]
78    remotes_config_location: RwLock<PathBuf>,
79    #[component(default = "create_instance_config")]
80    instance_config: RwLock<InstanceConfig>,
81    #[component(default = "create_graphql_server_config")]
82    graphql_server_config: RwLock<GraphQLServerConfig>,
83    #[component(default = "create_plugins_config")]
84    plugins_config: RwLock<PluginsConfig>,
85    #[component(default = "create_remotes_config")]
86    remotes_config: RwLock<RemotesConfig>,
87}
88
89// #[async_trait]
90#[component_alias]
91impl ConfigManager for ConfigManagerImpl {
92    fn get_instance_config_location(&self) -> PathBuf {
93        let reader = self.instance_config_location.read().unwrap();
94        reader.clone()
95    }
96
97    fn set_instance_config_location(&self, instance_config_location: PathBuf) {
98        let mut writer = self.instance_config_location.write().unwrap();
99        *writer = instance_config_location;
100    }
101
102    fn get_graphql_server_config_location(&self) -> PathBuf {
103        let reader = self.graphql_server_config_location.read().unwrap();
104        reader.clone()
105    }
106
107    fn set_graphql_server_config_location(&self, graphql_server_config_location: PathBuf) {
108        let mut writer = self.graphql_server_config_location.write().unwrap();
109        *writer = graphql_server_config_location;
110    }
111
112    fn get_plugins_config_location(&self) -> PathBuf {
113        let reader = self.plugins_config_location.read().unwrap();
114        reader.clone()
115    }
116
117    fn set_plugins_config_location(&self, plugins_config_location: PathBuf) {
118        let mut writer = self.plugins_config_location.write().unwrap();
119        *writer = plugins_config_location;
120    }
121
122    fn get_remotes_config_location(&self) -> PathBuf {
123        let reader = self.remotes_config_location.read().unwrap();
124        reader.clone()
125    }
126
127    fn set_remotes_config_location(&self, remotes_config_location: PathBuf) {
128        let mut writer = self.remotes_config_location.write().unwrap();
129        *writer = remotes_config_location;
130    }
131
132    fn get_instance_config(&self) -> InstanceConfig {
133        let reader = self.instance_config.read().unwrap();
134        reader.clone()
135    }
136
137    fn set_instance_config(&self, instance_config: InstanceConfig) {
138        let mut writer = self.instance_config.write().unwrap();
139        *writer = instance_config;
140    }
141
142    fn read_instance_config(&self) {
143        let location = self.get_instance_config_location();
144        match std::fs::read_to_string(&location) {
145            Ok(toml_string) => match toml::from_str(&toml_string) {
146                Ok(instance_config) => {
147                    self.set_instance_config(instance_config);
148                }
149                Err(_) => {
150                    error!("Failed to load the instance configuration from {}: Invalid TOML", location.to_str().unwrap_or(""));
151                }
152            },
153            Err(_) => {
154                error!("Failed to load the instance configuration from {}: File does not exist", location.to_str().unwrap_or(""));
155            }
156        }
157    }
158
159    fn set_instance_name(&self, instance_name: &str) {
160        let mut writer = self.instance_config.write().unwrap();
161        writer.name = instance_name.to_string();
162    }
163
164    fn set_instance_description(&self, instance_description: &str) {
165        let mut writer = self.instance_config.write().unwrap();
166        writer.description = instance_description.to_string();
167    }
168
169    fn get_graphql_server_config(&self) -> GraphQLServerConfig {
170        let reader = self.graphql_server_config.read().unwrap();
171        reader.clone()
172    }
173
174    fn set_graphql_server_config(&self, graphql_server_config: GraphQLServerConfig) {
175        let mut writer = self.graphql_server_config.write().unwrap();
176        *writer = graphql_server_config;
177    }
178
179    fn read_graphql_server_config(&self) {
180        let location = self.get_graphql_server_config_location();
181        match std::fs::read_to_string(&location) {
182            Ok(toml_string) => match toml::from_str(&toml_string) {
183                Ok(graphql_server_config) => {
184                    debug!("Loaded graphql configuration from {}", location.to_str().unwrap_or(""));
185                    self.set_graphql_server_config(graphql_server_config);
186                }
187                Err(_) => {
188                    error!("Failed to load the graphql configuration from {}: Invalid TOML", location.to_str().unwrap_or(""));
189                }
190            },
191            Err(_) => {
192                error!("Failed to load the graphql configuration from {}: File does not exist", location.to_str().unwrap_or(""));
193            }
194        }
195    }
196
197    fn set_graphql_hostname(&self, hostname: &str) {
198        let mut writer = self.graphql_server_config.write().unwrap();
199        writer.hostname = Some(String::from(hostname));
200    }
201
202    fn set_graphql_port(&self, port: u16) {
203        let mut writer = self.graphql_server_config.write().unwrap();
204        writer.port = Some(port);
205    }
206
207    fn set_graphql_secure(&self, secure: bool) {
208        let mut writer = self.graphql_server_config.write().unwrap();
209        writer.secure = Some(secure);
210    }
211
212    fn set_graphql_ssl_certificate_path(&self, ssl_certificate_path: &str) {
213        let mut writer = self.graphql_server_config.write().unwrap();
214        writer.ssl_certificate_path = Some(String::from(ssl_certificate_path));
215    }
216
217    fn set_graphql_ssl_private_key_path(&self, ssl_private_key_path: &str) {
218        let mut writer = self.graphql_server_config.write().unwrap();
219        writer.ssl_private_key_path = Some(String::from(ssl_private_key_path));
220    }
221
222    fn set_graphql_shutdown_timeout(&self, shutdown_timeout: u64) {
223        let mut writer = self.graphql_server_config.write().unwrap();
224        writer.shutdown_timeout = Some(shutdown_timeout);
225    }
226
227    fn set_graphql_workers(&self, workers: usize) {
228        let mut writer = self.graphql_server_config.write().unwrap();
229        writer.workers = Some(workers);
230    }
231
232    fn get_graphql_default_context_path(&self) -> Option<String> {
233        self.graphql_server_config.read().unwrap().default_context_path()
234    }
235
236    fn set_graphql_default_context_path(&self, default_context_path: String) {
237        let mut writer = self.graphql_server_config.write().unwrap();
238        writer.default_context_path = Some(default_context_path);
239    }
240
241    fn get_plugins_config(&self) -> PluginsConfig {
242        let reader = self.plugins_config.read().unwrap();
243        reader.clone()
244    }
245
246    fn set_plugins_config(&self, plugins_config: PluginsConfig) {
247        let mut writer = self.plugins_config.write().unwrap();
248        *writer = plugins_config;
249    }
250
251    fn read_plugins_config(&self) {
252        let location = self.get_plugins_config_location();
253        match std::fs::read_to_string(&location) {
254            Ok(toml_string) => match toml::from_str(&toml_string) {
255                Ok(plugins_config) => {
256                    self.set_plugins_config(plugins_config);
257                }
258                Err(_) => {
259                    error!("Failed to load the plugins configuration from {}: Invalid TOML", location.to_str().unwrap_or(""));
260                }
261            },
262            Err(_) => {
263                error!("Failed to load the plugins configuration from {}: File does not exist", location.to_str().unwrap_or(""));
264            }
265        }
266    }
267
268    fn set_disable_all_plugins(&self, disabled: bool) {
269        let mut writer = self.plugins_config.write().unwrap();
270        writer.disabled = Some(disabled);
271    }
272
273    fn set_disabled_plugins(&self, disabled_plugins: Vec<String>) {
274        let mut writer = self.plugins_config.write().unwrap();
275        writer.disabled_plugins = Some(disabled_plugins);
276    }
277
278    fn set_enabled_plugins(&self, enabled_plugins: Vec<String>) {
279        let mut writer = self.plugins_config.write().unwrap();
280        writer.enabled_plugins = Some(enabled_plugins);
281    }
282
283    fn set_disable_hot_deploy(&self, disable_hot_deploy: bool) {
284        let mut writer = self.plugins_config.write().unwrap();
285        writer.hot_deploy = Some(!disable_hot_deploy);
286    }
287
288    fn set_hot_deploy_location(&self, hot_deploy_location: Option<String>) {
289        let mut writer = self.plugins_config.write().unwrap();
290        writer.hot_deploy_location = hot_deploy_location;
291    }
292
293    fn set_install_location(&self, install_location: Option<String>) {
294        let mut writer = self.plugins_config.write().unwrap();
295        writer.install_location = install_location;
296    }
297
298    fn get_remotes_config(&self) -> RemotesConfig {
299        let reader = self.remotes_config.read().unwrap();
300        reader.clone()
301    }
302
303    fn set_remotes_config(&self, remotes_config: RemotesConfig) {
304        let mut writer = self.remotes_config.write().unwrap();
305        *writer = remotes_config;
306    }
307
308    fn read_remotes_config(&self) {
309        let location = self.get_remotes_config_location();
310        match std::fs::read_to_string(&location) {
311            Ok(toml_string) => match toml::from_str(&toml_string) {
312                Ok(remotes_config) => {
313                    self.set_remotes_config(remotes_config);
314                }
315                Err(e) => {
316                    error!("Failed to load the remotes configuration from {}: Invalid TOML: {}", location.to_str().unwrap_or(""), e);
317                }
318            },
319            Err(e) => {
320                error!("Failed to load the remotes configuration from {}: {}", location.to_str().unwrap_or(""), e);
321            }
322        }
323    }
324
325    fn write_remotes_config(&self) {
326        let location = self.get_remotes_config_location();
327        let remotes_config = self.get_remotes_config();
328        match toml::to_string(&remotes_config) {
329            Ok(toml_string) => match std::fs::write(location.clone(), toml_string) {
330                Ok(_) => info!("Saved remote configuration to {}", location.to_str().unwrap_or("")),
331                Err(e) => error!("Failed to save remote configuration to {}: {}", location.to_str().unwrap_or(""), e),
332            },
333            Err(e) => error!("Failed to save remote configuration to {}: {}", location.to_str().unwrap_or(""), e),
334        }
335    }
336}
337
338#[async_trait]
339impl Lifecycle for ConfigManagerImpl {
340    async fn init(&self) {
341        self.read_graphql_server_config();
342        self.read_instance_config();
343        self.read_plugins_config();
344        self.read_remotes_config();
345    }
346}