inspirer_foundation/component/
config.rs

1use std::sync::Arc;
2
3use crate::{service::Service, Result};
4use config::{Config as LocalRepository, Source, Value, ConfigError};
5use serde::Deserialize;
6use tokio::sync::RwLock;
7
8use super::ComponentConstructor;
9
10pub struct ConfigComponentSimpleConstructor;
11
12#[async_trait]
13impl ComponentConstructor for ConfigComponentSimpleConstructor {
14    async fn constructor(&self, service: Service) -> Result<()> {
15        service.register_component(Config::default()).await;
16
17        Ok(())
18    }
19}
20
21#[derive(Debug, Clone, Default)]
22pub struct Config {
23    inner: Arc<RwLock<LocalRepository>>,
24}
25
26#[async_trait]
27pub trait ConfigAdapter {
28    async fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T>;
29    async fn try_get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<Option<T>>;
30
31    async fn merge<T>(&self, source: T) -> Result<()>
32    where
33        T: 'static,
34        T: Source + Send + Sync;
35
36    async fn set<T>(&self, key: &str, value: T) -> Result<()>
37    where
38        T: Into<Value> + Send;
39}
40
41#[async_trait]
42impl ConfigAdapter for Config {
43    async fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
44        self.inner.read().await.get(key).map_err(Into::into)
45    }
46
47    async fn try_get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<Option<T>> {
48        self.inner.read().await.get(key)
49            .map(|s| Some(s))
50            .or_else(|err| {
51                match err {
52                    ConfigError::NotFound(_) => Ok(None),
53                    _ => Err(err)
54                }
55            })
56            .map_err(Into::into)
57    }
58
59    async fn merge<T>(&self, source: T) -> Result<()>
60    where
61        T: 'static,
62        T: Source + Send + Sync,
63    {
64        {
65            self.inner.write().await.merge(source)?;
66        }
67
68        Ok(())
69    }
70
71    async fn set<T>(&self, key: &str, value: T) -> Result<()>
72    where
73        T: Into<Value> + Send,
74    {
75        {
76            self.inner.write().await.set(key, value)?;
77        }
78
79        Ok(())
80    }
81}
82
83#[async_trait]
84impl ConfigAdapter for Service {
85    async fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
86        self.component_read_guard::<Config>().await.get::<T>(key).await
87    }
88
89    async fn try_get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<Option<T>> {
90        self.component_read_guard::<Config>().await.try_get::<T>(key).await
91    }
92
93    async fn merge<T>(&self, source: T) -> Result<()>
94    where
95        T: 'static,
96        T: Source + Send + Sync,
97    {
98        self.component_read_guard::<Config>().await.merge(source).await
99    }
100
101    async fn set<T>(&self, key: &str, value: T) -> Result<()>
102    where
103        T: Into<Value> + Send,
104    {
105        self.component_read_guard::<Config>().await.set(key, value).await
106    }
107}