doido_cache/global.rs
1//! Process-global default cache store, built once from config at boot.
2//!
3//! Mirrors `doido-model`'s connection pool: [`init`] builds the store described
4//! by the current environment's `cache` config and installs it; handlers read it
5//! via [`store`]. Apps that want several named stores can still use
6//! [`crate::CacheRegistry`] directly.
7
8use crate::store::CacheStore;
9use doido_core::Result;
10use std::sync::{Arc, OnceLock};
11
12static CACHE: OnceLock<Arc<dyn CacheStore>> = OnceLock::new();
13
14/// Builds the cache store from `config/<env>.yml` and installs it as the global
15/// default, returning a handle. Idempotent: if already initialised, the existing
16/// store is returned and the freshly built one discarded. Call once at boot.
17pub async fn init() -> Result<Arc<dyn CacheStore>> {
18 if let Some(existing) = CACHE.get() {
19 return Ok(existing.clone());
20 }
21 let store = crate::config::load().build().await?;
22 let _ = CACHE.set(store);
23 Ok(CACHE.get().expect("cache was just set").clone())
24}
25
26/// Installs an already-built store as the global default (e.g. in tests).
27/// Returns `Err` with the store back if one was already installed.
28pub fn set_store(store: Arc<dyn CacheStore>) -> std::result::Result<(), Arc<dyn CacheStore>> {
29 CACHE.set(store)
30}
31
32/// Returns the global cache store, panicking if [`init`]/[`set_store`] was never
33/// called. Use from request handlers where boot is guaranteed to have run.
34pub fn store() -> Arc<dyn CacheStore> {
35 CACHE
36 .get()
37 .expect("cache not initialised; call doido_cache::global::init() at boot")
38 .clone()
39}
40
41/// Returns the global cache store if installed, else `None`.
42pub fn try_store() -> Option<Arc<dyn CacheStore>> {
43 CACHE.get().cloned()
44}