use crate::{ChannelAdapter, Error, Event, NotificationConfig, NotificationSystem};
use std::sync::Arc;
use tokio::sync::{Mutex, OnceCell};
static GLOBAL_SYSTEM: OnceCell<Arc<Mutex<NotificationSystem>>> = OnceCell::const_new();
static INITIALIZED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
pub async fn initialize(config: NotificationConfig) -> Result<(), Error> {
if INITIALIZED.swap(true, std::sync::atomic::Ordering::SeqCst) {
return Err(Error::custom("notify the system has been initialized"));
}
let system = Arc::new(Mutex::new(NotificationSystem::new(config).await?));
GLOBAL_SYSTEM
.set(system)
.map_err(|_| Error::custom("unable to set up global notification system"))?;
Ok(())
}
pub async fn start(adapters: Vec<Arc<dyn ChannelAdapter>>) -> Result<(), Error> {
let system = get_system().await?;
let system_clone = Arc::clone(&system);
tokio::spawn(async move {
let mut system_guard = system_clone.lock().await;
if let Err(e) = system_guard.start(adapters).await {
tracing::error!("notify the system to start failed: {}", e);
}
});
Ok(())
}
pub async fn initialize_and_start(config: NotificationConfig) -> Result<(), Error> {
initialize(config.clone()).await?;
let adapters = crate::create_adapters(&config.adapters).expect("failed to create adapters");
start(adapters).await?;
Ok(())
}
pub async fn send_event(event: Event) -> Result<(), Error> {
let system = get_system().await?;
let system_guard = system.lock().await;
system_guard.send_event(event).await
}
pub fn shutdown() -> Result<(), Error> {
if let Some(system) = GLOBAL_SYSTEM.get() {
let system_guard = system.blocking_lock();
system_guard.shutdown();
Ok(())
} else {
Err(Error::custom("notification system not initialized"))
}
}
async fn get_system() -> Result<Arc<Mutex<NotificationSystem>>, Error> {
GLOBAL_SYSTEM
.get()
.cloned()
.ok_or_else(|| Error::custom("notification system not initialized"))
}