openzeppelin_monitor/repositories/
trigger.rs1#![allow(clippy::result_large_err)]
8
9use std::{collections::HashMap, path::Path};
10
11use async_trait::async_trait;
12
13use crate::{
14 models::{ConfigLoader, Trigger},
15 repositories::error::RepositoryError,
16};
17
18#[derive(Clone)]
20pub struct TriggerRepository {
21 pub triggers: HashMap<String, Trigger>,
23}
24
25impl TriggerRepository {
26 pub async fn new(path: Option<&Path>) -> Result<Self, RepositoryError> {
31 let triggers = Self::load_all(path).await?;
32 Ok(TriggerRepository { triggers })
33 }
34}
35
36#[async_trait]
41pub trait TriggerRepositoryTrait: Clone {
42 async fn new(path: Option<&Path>) -> Result<Self, RepositoryError>
44 where
45 Self: Sized;
46
47 async fn load_all(path: Option<&Path>) -> Result<HashMap<String, Trigger>, RepositoryError>;
52
53 fn get(&self, trigger_id: &str) -> Option<Trigger>;
57
58 fn get_all(&self) -> HashMap<String, Trigger>;
62}
63
64#[async_trait]
65impl TriggerRepositoryTrait for TriggerRepository {
66 async fn new(path: Option<&Path>) -> Result<Self, RepositoryError> {
67 TriggerRepository::new(path).await
68 }
69
70 async fn load_all(path: Option<&Path>) -> Result<HashMap<String, Trigger>, RepositoryError> {
71 Trigger::load_all(path).await.map_err(|e| {
72 RepositoryError::load_error(
73 "Failed to load triggers",
74 Some(Box::new(e)),
75 Some(HashMap::from([(
76 "path".to_string(),
77 path.map_or_else(|| "default".to_string(), |p| p.display().to_string()),
78 )])),
79 )
80 })
81 }
82
83 fn get(&self, trigger_id: &str) -> Option<Trigger> {
84 self.triggers.get(trigger_id).cloned()
85 }
86
87 fn get_all(&self) -> HashMap<String, Trigger> {
88 self.triggers.clone()
89 }
90}
91
92#[derive(Clone)]
97pub struct TriggerService<T: TriggerRepositoryTrait> {
98 repository: T,
99}
100
101impl<T: TriggerRepositoryTrait> TriggerService<T> {
102 pub async fn new(
104 path: Option<&Path>,
105 ) -> Result<TriggerService<TriggerRepository>, RepositoryError> {
106 let repository = TriggerRepository::new(path).await?;
107 Ok(TriggerService { repository })
108 }
109
110 pub fn new_with_repository(repository: T) -> Result<Self, RepositoryError> {
112 Ok(TriggerService { repository })
113 }
114
115 pub async fn new_with_path(
117 path: Option<&Path>,
118 ) -> Result<TriggerService<TriggerRepository>, RepositoryError> {
119 let repository = TriggerRepository::new(path).await?;
120 Ok(TriggerService { repository })
121 }
122
123 pub fn get(&self, trigger_id: &str) -> Option<Trigger> {
125 self.repository.get(trigger_id)
126 }
127
128 pub fn get_all(&self) -> HashMap<String, Trigger> {
130 self.repository.get_all()
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137 use crate::repositories::error::RepositoryError;
138 use std::path::PathBuf;
139
140 #[tokio::test]
141 async fn test_load_error_messages() {
142 let invalid_path = PathBuf::from("/non/existent/path");
144 let result = TriggerRepository::load_all(Some(&invalid_path)).await;
145 assert!(result.is_err());
146 let err = result.unwrap_err();
147 match err {
148 RepositoryError::LoadError(message) => {
149 assert!(message.to_string().contains("Failed to load triggers"));
150 }
151 _ => panic!("Expected RepositoryError::LoadError"),
152 }
153 }
154}