rskit_messaging/
handler.rs1use std::sync::Arc;
4
5use async_trait::async_trait;
6use rskit_errors::AppResult;
7
8use crate::message::Message;
9
10#[async_trait]
15pub trait MessageHandler<T: Send + Sync + 'static>: Send + Sync + 'static {
16 async fn handle(&self, msg: Message<T>) -> AppResult<()>;
18}
19
20pub trait HandlerMiddleware<T: Send + Sync + 'static>: Send + Sync + 'static {
26 fn wrap(&self, next: Arc<dyn MessageHandler<T>>) -> Arc<dyn MessageHandler<T>>;
29}
30
31pub fn chain_handlers<T: Send + Sync + 'static>(
41 base: Arc<dyn MessageHandler<T>>,
42 middlewares: &[Arc<dyn HandlerMiddleware<T>>],
43) -> Arc<dyn MessageHandler<T>> {
44 let mut handler = base;
45 for mw in middlewares.iter().rev() {
46 handler = mw.wrap(handler);
47 }
48 handler
49}
50
51pub fn middleware_fn<T, F>(f: F) -> impl HandlerMiddleware<T>
67where
68 T: Send + Sync + 'static,
69 F: Fn(Arc<dyn MessageHandler<T>>) -> Arc<dyn MessageHandler<T>> + Send + Sync + 'static,
70{
71 FnMiddleware {
72 func: f,
73 _marker: std::marker::PhantomData,
74 }
75}
76
77struct FnMiddleware<T, F> {
78 func: F,
79 _marker: std::marker::PhantomData<T>,
80}
81
82impl<T, F> HandlerMiddleware<T> for FnMiddleware<T, F>
83where
84 T: Send + Sync + 'static,
85 F: Fn(Arc<dyn MessageHandler<T>>) -> Arc<dyn MessageHandler<T>> + Send + Sync + 'static,
86{
87 fn wrap(&self, next: Arc<dyn MessageHandler<T>>) -> Arc<dyn MessageHandler<T>> {
88 (self.func)(next)
89 }
90}
91
92pub struct FnHandler<T, F, Fut>
105where
106 T: Send + Sync + 'static,
107 F: Fn(Message<T>) -> Fut + Send + Sync + 'static,
108 Fut: std::future::Future<Output = AppResult<()>> + Send + 'static,
109{
110 func: F,
111 _marker: std::marker::PhantomData<T>,
112}
113
114impl<T, F, Fut> FnHandler<T, F, Fut>
115where
116 T: Send + Sync + 'static,
117 F: Fn(Message<T>) -> Fut + Send + Sync + 'static,
118 Fut: std::future::Future<Output = AppResult<()>> + Send + 'static,
119{
120 pub const fn new(func: F) -> Self {
122 Self {
123 func,
124 _marker: std::marker::PhantomData,
125 }
126 }
127}
128
129#[async_trait]
130impl<T, F, Fut> MessageHandler<T> for FnHandler<T, F, Fut>
131where
132 T: Send + Sync + 'static,
133 F: Fn(Message<T>) -> Fut + Send + Sync + 'static,
134 Fut: std::future::Future<Output = AppResult<()>> + Send + 'static,
135{
136 async fn handle(&self, msg: Message<T>) -> AppResult<()> {
137 (self.func)(msg).await
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use std::sync::atomic::{AtomicU32, Ordering};
144
145 use super::*;
146
147 #[tokio::test]
148 async fn fn_handler_processes_message() {
149 let counter = Arc::new(AtomicU32::new(0));
150 let c = counter.clone();
151 let handler = FnHandler::new(move |_msg: Message<String>| {
152 let c = c.clone();
153 async move {
154 c.fetch_add(1, Ordering::SeqCst);
155 Ok(())
156 }
157 });
158
159 let msg = Message::new("t", "hello".to_string());
160 handler.handle(msg).await.unwrap();
161 assert_eq!(counter.load(Ordering::SeqCst), 1);
162 }
163
164 struct CountingMiddleware {
166 counter: Arc<AtomicU32>,
167 }
168
169 struct CountingHandler<T: Send + Sync + 'static> {
170 counter: Arc<AtomicU32>,
171 next: Arc<dyn MessageHandler<T>>,
172 }
173
174 #[async_trait]
175 impl<T: Send + Sync + 'static> MessageHandler<T> for CountingHandler<T> {
176 async fn handle(&self, msg: Message<T>) -> AppResult<()> {
177 self.counter.fetch_add(1, Ordering::SeqCst);
178 self.next.handle(msg).await
179 }
180 }
181
182 impl<T: Send + Sync + 'static> HandlerMiddleware<T> for CountingMiddleware {
183 fn wrap(&self, next: Arc<dyn MessageHandler<T>>) -> Arc<dyn MessageHandler<T>> {
184 Arc::new(CountingHandler {
185 counter: self.counter.clone(),
186 next,
187 })
188 }
189 }
190
191 #[tokio::test]
192 async fn middleware_chain_applies_in_order() {
193 let mw_counter = Arc::new(AtomicU32::new(0));
194 let base_counter = Arc::new(AtomicU32::new(0));
195
196 let bc = base_counter.clone();
197 let base: Arc<dyn MessageHandler<String>> =
198 Arc::new(FnHandler::new(move |_msg: Message<String>| {
199 let bc = bc.clone();
200 async move {
201 bc.fetch_add(1, Ordering::SeqCst);
202 Ok(())
203 }
204 }));
205
206 let mw: Arc<dyn HandlerMiddleware<String>> = Arc::new(CountingMiddleware {
207 counter: mw_counter.clone(),
208 });
209
210 let chained = chain_handlers(base, &[mw]);
211 let msg = Message::new("t", "data".to_string());
212 chained.handle(msg).await.unwrap();
213
214 assert_eq!(mw_counter.load(Ordering::SeqCst), 1);
215 assert_eq!(base_counter.load(Ordering::SeqCst), 1);
216 }
217}