1use std::sync::Arc;
4
5use arc_swap::ArcSwap;
6use tokio::sync::Mutex;
7
8pub use reloadable_core as core;
9
10pub struct Reloadable<T, R> {
12 value: ArcSwap<T>,
14 loader: Mutex<R>,
16}
17
18impl<T, L> Reloadable<T, L> {
19 pub fn new(loader: L, initial_value: Arc<T>) -> Self {
21 let loader = Mutex::new(loader);
22 let value = ArcSwap::new(initial_value);
23 Self { loader, value }
24 }
25
26 pub fn get(&self) -> Arc<T> {
28 self.value.load_full()
29 }
30
31 pub fn set(&self, value: Arc<T>) -> Arc<T> {
33 self.value.swap(value)
34 }
35}
36
37impl<T, L> Reloadable<T, L>
38where
39 L: reloadable_core::Loader<Value = T>,
40{
41 pub async fn init_load(mut loader: L) -> Result<(Self, Arc<T>), L::Error> {
43 let loaded = loader.load().await?;
44 let loaded = Arc::new(loaded);
45 let reloadable = Self::new(loader, Arc::clone(&loaded));
46 Ok((reloadable, loaded))
47 }
48
49 pub async fn reload(&self) -> Result<Arc<T>, L::Error> {
53 let mut loader = self.loader.lock().await;
54 let reloaded = loader.load().await?;
55 let reloaded = Arc::new(reloaded);
56 drop(self.set(Arc::clone(&reloaded)));
57 Ok(reloaded)
58 }
59}
60
61impl<T, R> std::fmt::Debug for Reloadable<T, R> {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 f.debug_struct("Reloadable").finish_non_exhaustive()
64 }
65}