inspirer_foundation/component/
config.rs1use 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}