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/// };
56///
57/// // complete initialization and startup in one step
58/// initialize_and_start(config).await?
59/// }
60/// ```
61pub async fn initialize_and_start(config: NotificationConfig) -> Result<(), Error> {
62    // initialize the system first
63    initialize(config.clone()).await?;
64
65    // create an adapter
66    let adapters = crate::create_adapters(&config.adapters).expect("failed to create adapters");
67
68    // start the system
69    start(adapters).await?;
70
71    Ok(())
72}
73
74/// send events to notification system
75pub async fn send_event(event: Event) -> Result<(), Error> {
76    let system = get_system().await?;
77    let system_guard = system.lock().await;
78    system_guard.send_event(event).await
79}
80
81/// turn off the notification system
82pub fn shutdown() -> Result<(), Error> {
83    if let Some(system) = GLOBAL_SYSTEM.get() {
84        let system_guard = system.blocking_lock();
85        system_guard.shutdown();
86        Ok(())
87    } else {
88        Err(Error::custom("notification system not initialized"))
89    }
90}
91
92/// get system instance
93async fn get_system() -> Result<Arc<Mutex<NotificationSystem>>, Error> {
94    GLOBAL_SYSTEM
95        .get()
96        .cloned()
97        .ok_or_else(|| Error::custom("notification system not initialized"))
98}