1#![allow(clippy::disallowed_types)]
14
15use aura_core::effects::ExecutionMode;
16use std::collections::{HashMap, HashSet};
17use std::fmt;
18use std::sync::{Arc, RwLock};
19
20use super::executor::EffectHandler;
21
22#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
24pub enum EffectType {
25 Crypto,
26 Storage,
27 Transport,
28 Journal,
29}
30
31impl EffectType {
32 pub const fn as_str(self) -> &'static str {
33 match self {
34 EffectType::Crypto => "crypto",
35 EffectType::Storage => "storage",
36 EffectType::Transport => "transport",
37 EffectType::Journal => "journal",
38 }
39 }
40}
41
42impl fmt::Display for EffectType {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 f.write_str(self.as_str())
45 }
46}
47
48#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
50pub struct EffectOperation(&'static str);
51
52impl EffectOperation {
53 pub const fn new(name: &'static str) -> Self {
54 Self(name)
55 }
56
57 pub const fn as_str(self) -> &'static str {
58 self.0
59 }
60}
61
62impl fmt::Display for EffectOperation {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 f.write_str(self.0)
65 }
66}
67
68impl From<&'static str> for EffectOperation {
69 fn from(value: &'static str) -> Self {
70 Self(value)
71 }
72}
73
74#[derive(Debug)]
76pub struct EffectRegistry {
77 shared: Arc<EffectRegistryShared>,
78 execution_mode: ExecutionMode,
79}
80
81#[derive(Debug)]
82struct EffectRegistryShared {
83 handlers: RwLock<HashMap<EffectKey, Arc<dyn std::any::Any + Send + Sync>>>,
84}
85
86impl EffectRegistry {
87 pub fn new(execution_mode: ExecutionMode) -> Self {
89 Self {
90 shared: Arc::new(EffectRegistryShared {
91 handlers: RwLock::new(HashMap::new()),
92 }),
93 execution_mode,
94 }
95 }
96
97 pub fn register_effect_handler<T, H>(
99 &self,
100 effect_type: EffectType,
101 operation: EffectOperation,
102 handler: H,
103 ) -> Result<(), EffectRegistryError>
104 where
105 T: Send + Sync + 'static,
106 H: EffectHandler<T> + 'static,
107 {
108 let handler: Arc<dyn EffectHandler<T>> = Arc::new(handler);
109 self.register(effect_type, operation, handler)
110 }
111
112 pub fn get_effect_handler<T: Send + Sync + 'static>(
114 &self,
115 effect_type: EffectType,
116 operation: EffectOperation,
117 ) -> Result<Option<Arc<dyn EffectHandler<T>>>, EffectRegistryError> {
118 Ok(self
119 .get::<Arc<dyn EffectHandler<T>>>(effect_type, operation)?
120 .map(|handler| handler.as_ref().clone()))
121 }
122
123 pub fn register<T: Send + Sync + 'static>(
125 &self,
126 effect_type: EffectType,
127 operation: EffectOperation,
128 handler: T,
129 ) -> Result<(), EffectRegistryError> {
130 let key = EffectKey::new(effect_type, operation);
131
132 let mut handlers = self
133 .shared
134 .handlers
135 .write()
136 .map_err(|_| EffectRegistryError::LockError)?;
137
138 handlers.insert(key, Arc::new(handler));
139 Ok(())
140 }
141
142 pub fn get<T: Send + Sync + 'static>(
144 &self,
145 effect_type: EffectType,
146 operation: EffectOperation,
147 ) -> Result<Option<Arc<T>>, EffectRegistryError> {
148 let key = EffectKey::new(effect_type, operation);
149
150 let handlers = self
151 .shared
152 .handlers
153 .read()
154 .map_err(|_| EffectRegistryError::LockError)?;
155
156 Ok(handlers
157 .get(&key)
158 .and_then(|handler| handler.clone().downcast::<T>().ok()))
159 }
160
161 pub fn has_handler(&self, effect_type: EffectType, operation: EffectOperation) -> bool {
163 let key = EffectKey::new(effect_type, operation);
164
165 self.shared
166 .handlers
167 .read()
168 .map(|handlers| handlers.contains_key(&key))
169 .unwrap_or(false)
170 }
171
172 pub fn effect_types(&self) -> Vec<EffectType> {
174 self.shared
175 .handlers
176 .read()
177 .map(|handlers| {
178 handlers
179 .keys()
180 .map(|key| key.effect_type)
181 .collect::<HashSet<_>>()
182 .into_iter()
183 .collect()
184 })
185 .unwrap_or_default()
186 }
187
188 pub fn operations(&self, effect_type: EffectType) -> Vec<EffectOperation> {
190 self.shared
191 .handlers
192 .read()
193 .map(|handlers| {
194 handlers
195 .keys()
196 .filter(|key| key.effect_type == effect_type)
197 .map(|key| key.operation)
198 .collect()
199 })
200 .unwrap_or_default()
201 }
202
203 pub fn clear(&self) -> Result<(), EffectRegistryError> {
205 let mut handlers = self
206 .shared
207 .handlers
208 .write()
209 .map_err(|_| EffectRegistryError::LockError)?;
210
211 handlers.clear();
212 Ok(())
213 }
214
215 pub fn execution_mode(&self) -> ExecutionMode {
217 self.execution_mode
218 }
219}
220
221impl Clone for EffectRegistry {
222 fn clone(&self) -> Self {
223 Self {
224 shared: Arc::clone(&self.shared),
225 execution_mode: self.execution_mode,
226 }
227 }
228}
229
230#[derive(Debug, Clone, Hash, Eq, PartialEq)]
232struct EffectKey {
233 effect_type: EffectType,
234 operation: EffectOperation,
235}
236
237impl EffectKey {
238 fn new(effect_type: EffectType, operation: EffectOperation) -> Self {
239 Self {
240 effect_type,
241 operation,
242 }
243 }
244}
245
246#[derive(Debug, thiserror::Error)]
248pub enum EffectRegistryError {
249 #[error("Registry lock error")]
250 LockError,
251 #[error("Handler not found: {effect_type}.{operation}")]
252 HandlerNotFound {
253 effect_type: EffectType,
254 operation: EffectOperation,
255 },
256 #[error("Handler type mismatch")]
257 TypeMismatch,
258 #[error("Registration failed: {reason}")]
259 RegistrationFailed { reason: String },
260}
261
262pub trait EffectRegistryExt {
264 fn register_crypto_handler<T: Send + Sync + 'static>(
266 &self,
267 operation: EffectOperation,
268 handler: T,
269 ) -> Result<(), EffectRegistryError>;
270
271 fn register_storage_handler<T: Send + Sync + 'static>(
273 &self,
274 operation: EffectOperation,
275 handler: T,
276 ) -> Result<(), EffectRegistryError>;
277
278 fn register_transport_handler<T: Send + Sync + 'static>(
280 &self,
281 operation: EffectOperation,
282 handler: T,
283 ) -> Result<(), EffectRegistryError>;
284
285 fn register_journal_handler<T: Send + Sync + 'static>(
287 &self,
288 operation: EffectOperation,
289 handler: T,
290 ) -> Result<(), EffectRegistryError>;
291}
292
293impl EffectRegistryExt for EffectRegistry {
294 fn register_crypto_handler<T: Send + Sync + 'static>(
295 &self,
296 operation: EffectOperation,
297 handler: T,
298 ) -> Result<(), EffectRegistryError> {
299 self.register(EffectType::Crypto, operation, handler)
300 }
301
302 fn register_storage_handler<T: Send + Sync + 'static>(
303 &self,
304 operation: EffectOperation,
305 handler: T,
306 ) -> Result<(), EffectRegistryError> {
307 self.register(EffectType::Storage, operation, handler)
308 }
309
310 fn register_transport_handler<T: Send + Sync + 'static>(
311 &self,
312 operation: EffectOperation,
313 handler: T,
314 ) -> Result<(), EffectRegistryError> {
315 self.register(EffectType::Transport, operation, handler)
316 }
317
318 fn register_journal_handler<T: Send + Sync + 'static>(
319 &self,
320 operation: EffectOperation,
321 handler: T,
322 ) -> Result<(), EffectRegistryError> {
323 self.register(EffectType::Journal, operation, handler)
324 }
325}