This commit is contained in:
houseme
2025-05-28 22:56:06 +08:00
parent 8660c2af12
commit d27ddcb8f7
4 changed files with 22 additions and 96 deletions

View File

@@ -1,6 +1,5 @@
use std::cell::OnceCell;
use crate::{create_adapters, Error, Event, NotifierConfig, NotifierSystem};
use std::sync::{atomic, Arc, Mutex};
use std::sync::{atomic, Arc};
use tokio::sync::{Mutex, OnceCell};
use tracing::instrument;
@@ -174,7 +173,7 @@ async fn get_system() -> Result<Arc<Mutex<NotifierSystem>>, Error> {
#[cfg(test)]
mod tests {
use crate::NotifierConfig;
use crate::{initialize, is_initialized, is_ready, NotifierConfig};
fn init_tracing() {
// Use try_init to avoid panic if already initialized
@@ -185,7 +184,7 @@ mod tests {
async fn test_initialize_success() {
init_tracing();
let config = NotifierConfig::default(); // assume there is a default configuration
let result = initialize(config).await;
let result = initialize(&config).await;
assert!(result.is_err(), "Initialization should not succeed");
assert!(!is_initialized(), "System should not be marked as initialized");
assert!(!is_ready(), "System should not be marked as ready");
@@ -195,8 +194,8 @@ mod tests {
async fn test_initialize_twice() {
init_tracing();
let config = NotifierConfig::default();
let _ = initialize(config.clone()).await; // first initialization
let result = initialize(config).await; // second initialization
let _ = initialize(&config.clone()).await; // first initialization
let result = initialize(&config).await; // second initialization
assert!(result.is_err(), "Initialization should succeed");
assert!(result.is_err(), "Re-initialization should fail");
}
@@ -209,7 +208,7 @@ mod tests {
adapters: Vec::new(),
..Default::default()
};
let result = initialize(config).await;
let result = initialize(&config).await;
assert!(result.is_err(), "Initialization should fail with empty adapters");
assert!(!is_initialized(), "System should not be marked as initialized after failure");
assert!(!is_ready(), "System should not be marked as ready after failure");
@@ -227,7 +226,7 @@ mod tests {
adapters: Vec::new(),
..Default::default()
};
let result = initialize(config).await;
let result = initialize(&config).await;
assert!(result.is_err(), "Initialization should fail with empty adapters");
assert!(!is_initialized(), "System should not be initialized after failed init");
assert!(!is_ready(), "System should not be ready after failed init");

View File

@@ -25,17 +25,18 @@ pub static GLOBAL_EVENT_CONFIG: Lazy<Mutex<Option<EventNotifierConfig>>> = Lazy:
/// EventManager Responsible for managing all operations of the event system
#[derive(Debug)]
pub struct EventManager {
api: Arc<ECStore>,
pub struct EventManager<S: StorageAPI> {
api: Arc<S>,
}
impl EventManager {
impl<S: StorageAPI> EventManager {
/// Create a new Event Manager
pub async fn new(api: Arc<ECStore>) -> Self {
pub async fn new(api: Arc<S>) -> Self {
// Update the global access point at the same time
{
let mut global_api = GLOBAL_STORE_API.lock().await;
*global_api = Some(api.clone());
if let Ok(mut global_api) = GLOBAL_STORE_API.lock() {
if let Some(store) = api.as_any().downcast_ref::<ECStore>() {
*global_api = Some(Arc::new(store.clone()));
}
}
Self { api }
@@ -76,12 +77,15 @@ impl EventManager {
/// The result of the operation
pub async fn create_config(&self, cfg: &EventNotifierConfig) -> Result<()> {
// Check whether the configuration already exists
if let Ok(_) = read_event_config(self.api.clone()).await {
if read_event_config(self.api.clone()).await.is_ok() {
return Err(Error::msg("The configuration already exists, use the update action"));
}
save_event_config(self.api.clone(), cfg).await?;
*GLOBAL_EVENT_CONFIG.lock().await = Some(cfg.clone());
*GLOBAL_EVENT_CONFIG
.lock()
.await
.map_err(|e| Error::msg(format!("Failed to acquire global config lock: {}", e)))? = Some(cfg.clone());
Ok(())
}
@@ -195,8 +199,7 @@ async fn save_event_config<S: StorageAPI>(api: Arc<S>, config: &EventNotifierCon
let config_file = get_event_config_file();
let data = config.marshal()?;
save_config(api, &config_file, data).await?;
Ok(())
save_config(api, &config_file, data).await;
}
/// Get the event profile path

View File

@@ -1,3 +1,3 @@
pub(crate) mod event;
mod manager;
pub(crate) mod manager;
pub(crate) mod queue;

View File

@@ -1,76 +0,0 @@
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
///TargetID - Holds the identity and name string of the notification target
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TargetID {
/// Destination ID
pub id: String,
/// Target name
pub name: String,
}
impl TargetID {
/// Create a new TargetID
pub fn new(id: impl Into<String>, name: impl Into<String>) -> Self {
Self {
id: id.into(),
name: name.into(),
}
}
/// Convert to ARN
pub fn to_arn(&self, region: &str) -> ARN {
ARN {
target_id: self.clone(),
region: region.to_string(),
}
}
/// The parsed string is TargetID
pub fn parse(s: &str) -> Result<Self, String> {
let tokens: Vec<&str> = s.split(':').collect();
if tokens.len() != 2 {
return Err(format!("Invalid TargetID format '{}'", s));
}
Ok(Self {
id: tokens[0].to_string(),
name: tokens[1].to_string(),
})
}
}
impl fmt::Display for TargetID {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.id, self.name)
}
}
impl Serialize for TargetID {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for TargetID {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
TargetID::parse(&s).map_err(serde::de::Error::custom)
}
}
/// ARN - Amazon Resource Name structure
#[derive(Debug, Clone)]
pub struct ARN {
/// Destination ID
pub target_id: TargetID,
/// region
pub region: String,
}