rustls_cert_reloadable/
lib.rs1use std::sync::Arc;
4
5use arc_swap::ArcSwap;
6use tokio::sync::Mutex;
7
8#[async_trait::async_trait]
10pub trait Loader {
11 type Value;
13 type Error;
15
16 async fn load(&mut self) -> Result<Self::Value, Self::Error>;
18}
19
20pub struct Reloadable<T, R> {
22 value: ArcSwap<T>,
24 loader: Mutex<R>,
26}
27
28impl<T, L> Reloadable<T, L> {
29 pub fn new(loader: L, initial_value: Arc<T>) -> Self {
31 let loader = Mutex::new(loader);
32 let value = ArcSwap::new(initial_value);
33 Self { loader, value }
34 }
35
36 pub fn get(&self) -> Arc<T> {
38 self.value.load_full()
39 }
40
41 pub fn set(&self, value: Arc<T>) -> Arc<T> {
43 self.value.swap(value)
44 }
45}
46
47impl<T, L> Reloadable<T, L>
48where
49 L: Loader<Value = T>,
50{
51 pub async fn init_load(mut loader: L) -> Result<(Self, Arc<T>), L::Error> {
53 let loaded = loader.load().await?;
54 let loaded = Arc::new(loaded);
55 let reloadable = Self::new(loader, Arc::clone(&loaded));
56 Ok((reloadable, loaded))
57 }
58
59 pub async fn reload(&self) -> Result<Arc<T>, L::Error> {
63 let mut loader = self.loader.lock().await;
64 let reloaded = loader.load().await?;
65 let reloaded = Arc::new(reloaded);
66 drop(self.set(Arc::clone(&reloaded)));
67 Ok(reloaded)
68 }
69}
70
71impl<T, R> std::fmt::Debug for Reloadable<T, R> {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 f.debug_struct("Reloadable").finish_non_exhaustive()
74 }
75}