event_notification/
global.rs

1use crate::{ChannelAdapter, Error, Event, NotificationConfig, NotificationSystem};
2use std::sync::Arc;
3use tokio::sync::{Mutex, OnceCell};
4
5static GLOBAL_SYSTEM: OnceCell<Arc<Mutex<NotificationSystem>>> = OnceCell::const_new();
6static INITIALIZED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
7
8/// initialize the global notification system
9pub async fn initialize(config: NotificationConfig) -> Result<(), Error> {
10    if INITIALIZED.swap(true, std::sync::atomic::Ordering::SeqCst) {
11        return Err(Error::custom("notify the system has been initialized"));
12    }
13
14    let system = Arc::new(Mutex::new(NotificationSystem::new(config).await?));
15    GLOBAL_SYSTEM
16        .set(system)
17        .map_err(|_| Error::custom("unable to set up global notification system"))?;
18    Ok(())
19}
20
21/// start the global notification system
22pub async fn start(adapters: Vec<Arc<dyn ChannelAdapter>>) -> Result<(), Error> {
23    let system = get_system().await?;
24
25    // create a new task to run the system
26    let system_clone = Arc::clone(&system);
27    tokio::spawn(async move {
28        let mut system_guard = system_clone.lock().await;
29        if let Err(e) = system_guard.start(adapters).await {
30            tracing::error!("notify the system to start failed: {}", e);
31        }
32    });
33
34    Ok(())
35}
36
37/// Initialize and start the global notification system
38///
39/// This method combines the functions of `initialize` and `start` to provide one-step setup:
40/// - initialize system configuration
41/// - create an adapter
42/// - start event listening
43///
44/// # Example
45///
46/// ```rust
47///  use event_notification::{initialize_and_start, NotificationConfig};
48///
49/// #[tokio::main]
50/// async fn main() -> Result<(), event_notification::Error> {
51/// let config = NotificationConfig {
52///     store_path: "./events".to_string(),
53///     channel_capacity: 100,
54///     adapters: vec![/* 适配器配置 */],
55///     http: Default::default(),
56/// };
57///
58/// // complete initialization and startup in one step
59/// initialize_and_start(config).await?
60/// }
61/// ```
62pub async fn initialize_and_start(config: NotificationConfig) -> Result<(), Error> {
63    // initialize the system first
64    initialize(config.clone()).await?;
65
66    // create an adapter
67    let adapters = crate::create_adapters(&config.adapters).expect("failed to create adapters");
68
69    // start the system
70    start(adapters).await?;
71
72    Ok(())
73}
74
75/// send events to notification system
76pub async fn send_event(event: Event) -> Result<(), Error> {
77    let system = get_system().await?;
78    let system_guard = system.lock().await;
79    system_guard.send_event(event).await
80}
81
82/// turn off the notification system
83pub fn shutdown() -> Result<(), Error> {
84    if let Some(system) = GLOBAL_SYSTEM.get() {
85        let system_guard = system.blocking_lock();
86        system_guard.shutdown();
87        Ok(())
88    } else {
89        Err(Error::custom("notification system not initialized"))
90    }
91}
92
93/// get system instance
94async fn get_system() -> Result<Arc<Mutex<NotificationSystem>>, Error> {
95    GLOBAL_SYSTEM
96        .get()
97        .cloned()
98        .ok_or_else(|| Error::custom("notification system not initialized"))
99}