use std::sync::OnceLock;
use crate::{cache::ProviderCache, refresh::RefreshRegistry};
#[derive(Debug, thiserror::Error)]
pub enum GlobalProviderError {
#[error("Global providers not initialized. Call init_global_providers() first.")]
NotInitialized,
#[error("Failed to initialize global providers: {0}")]
InitializationFailed(String),
}
static GLOBAL_CACHE: OnceLock<ProviderCache> = OnceLock::new();
static GLOBAL_REFRESH_REGISTRY: OnceLock<RefreshRegistry> = OnceLock::new();
#[derive(Default, Debug, Clone)]
pub struct ProviderConfig {
enable_dependency_injection: bool,
}
impl ProviderConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_dependency_injection(mut self) -> Self {
self.enable_dependency_injection = true;
self
}
pub fn init(self) -> Result<(), GlobalProviderError> {
GLOBAL_CACHE.get_or_init(ProviderCache::new);
let _refresh_registry = GLOBAL_REFRESH_REGISTRY.get_or_init(RefreshRegistry::new);
if self.enable_dependency_injection {
crate::injection::ensure_dependency_injection_initialized();
}
Ok(())
}
}
pub fn init() -> Result<(), GlobalProviderError> {
ProviderConfig::new().with_dependency_injection().init()
}
#[deprecated(
since = "0.1.0",
note = "Use init() or ProviderConfig::new().init() instead"
)]
pub fn init_global_providers() -> Result<(), GlobalProviderError> {
ProviderConfig::new().init()
}
pub fn get_global_cache() -> Result<&'static ProviderCache, GlobalProviderError> {
GLOBAL_CACHE
.get()
.ok_or(GlobalProviderError::NotInitialized)
}
pub fn get_global_refresh_registry() -> Result<&'static RefreshRegistry, GlobalProviderError> {
GLOBAL_REFRESH_REGISTRY
.get()
.ok_or(GlobalProviderError::NotInitialized)
}
pub fn is_initialized() -> bool {
GLOBAL_CACHE.get().is_some() && GLOBAL_REFRESH_REGISTRY.get().is_some()
}
pub fn ensure_initialized() -> Result<(), crate::errors::ProviderError> {
if !is_initialized() {
return Err(crate::errors::ProviderError::Configuration(
"Global providers not initialized. Call init() at application startup.".to_string(),
));
}
Ok(())
}
#[cfg(test)]
pub fn reset_global_providers() {
panic!("Global provider reset is not currently supported. Restart the application.");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_global_provider_initialization() {
if is_initialized() {
let _cache = get_global_cache().unwrap();
let _refresh = get_global_refresh_registry().unwrap();
return;
}
assert!(!is_initialized());
init_global_providers().unwrap();
assert!(is_initialized());
let _cache = get_global_cache().unwrap();
let _refresh = get_global_refresh_registry().unwrap();
}
#[test]
fn test_error_when_not_initialized() {
if is_initialized() {
return;
}
assert!(get_global_cache().is_err());
assert!(get_global_refresh_registry().is_err());
}
#[test]
fn test_get_functions_with_error_handling() {
init().unwrap();
let _cache = get_global_cache().unwrap();
let _refresh = get_global_refresh_registry().unwrap();
}
}