openzeppelin_monitor/repositories/
trigger.rs#![allow(clippy::result_large_err)]
use std::{collections::HashMap, path::Path};
use async_trait::async_trait;
use crate::{
models::{ConfigLoader, Trigger},
repositories::error::RepositoryError,
};
#[derive(Clone)]
pub struct TriggerRepository {
pub triggers: HashMap<String, Trigger>,
}
impl TriggerRepository {
pub async fn new(path: Option<&Path>) -> Result<Self, RepositoryError> {
let triggers = Self::load_all(path).await?;
Ok(TriggerRepository { triggers })
}
}
#[async_trait]
pub trait TriggerRepositoryTrait: Clone {
async fn new(path: Option<&Path>) -> Result<Self, RepositoryError>
where
Self: Sized;
async fn load_all(path: Option<&Path>) -> Result<HashMap<String, Trigger>, RepositoryError>;
fn get(&self, trigger_id: &str) -> Option<Trigger>;
fn get_all(&self) -> HashMap<String, Trigger>;
}
#[async_trait]
impl TriggerRepositoryTrait for TriggerRepository {
async fn new(path: Option<&Path>) -> Result<Self, RepositoryError> {
TriggerRepository::new(path).await
}
async fn load_all(path: Option<&Path>) -> Result<HashMap<String, Trigger>, RepositoryError> {
Trigger::load_all(path).await.map_err(|e| {
RepositoryError::load_error(
"Failed to load triggers",
Some(Box::new(e)),
Some(HashMap::from([(
"path".to_string(),
path.map_or_else(|| "default".to_string(), |p| p.display().to_string()),
)])),
)
})
}
fn get(&self, trigger_id: &str) -> Option<Trigger> {
self.triggers.get(trigger_id).cloned()
}
fn get_all(&self) -> HashMap<String, Trigger> {
self.triggers.clone()
}
}
#[derive(Clone)]
pub struct TriggerService<T: TriggerRepositoryTrait> {
repository: T,
}
impl<T: TriggerRepositoryTrait> TriggerService<T> {
pub async fn new(
path: Option<&Path>,
) -> Result<TriggerService<TriggerRepository>, RepositoryError> {
let repository = TriggerRepository::new(path).await?;
Ok(TriggerService { repository })
}
pub fn new_with_repository(repository: T) -> Result<Self, RepositoryError> {
Ok(TriggerService { repository })
}
pub async fn new_with_path(
path: Option<&Path>,
) -> Result<TriggerService<TriggerRepository>, RepositoryError> {
let repository = TriggerRepository::new(path).await?;
Ok(TriggerService { repository })
}
pub fn get(&self, trigger_id: &str) -> Option<Trigger> {
self.repository.get(trigger_id)
}
pub fn get_all(&self) -> HashMap<String, Trigger> {
self.repository.get_all()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::repositories::error::RepositoryError;
use std::path::PathBuf;
#[tokio::test]
async fn test_load_error_messages() {
let invalid_path = PathBuf::from("/non/existent/path");
let result = TriggerRepository::load_all(Some(&invalid_path)).await;
assert!(result.is_err());
let err = result.unwrap_err();
match err {
RepositoryError::LoadError(message) => {
assert!(message.to_string().contains("Failed to load triggers"));
}
_ => panic!("Expected RepositoryError::LoadError"),
}
}
}