rocketmq_model/common/chain.rs
1// Copyright 2023 The RocketMQ Rust Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Chain of responsibility pattern implementation.
16//!
17//! This module provides traits and types for implementing the chain of
18//! responsibility design pattern in RocketMQ.
19
20use std::cell::Cell;
21
22pub mod handler;
23
24pub use handler::Handler;
25
26/// Handler chain for managing a sequence of handlers.
27///
28/// This struct manages a collection of handlers and executes them in sequence.
29/// Each handler can process the request and decide whether to continue to the
30/// next handler in the chain.
31///
32/// # Type Parameters
33///
34/// * `T` - The type of the request/input
35/// * `R` - The type of the response/output
36///
37/// # Examples
38///
39/// ```
40/// use rocketmq_model::common::chain::{Handler, HandlerChain};
41///
42/// struct Increment;
43/// struct Double;
44///
45/// impl Handler<i32, i32> for Increment {
46/// fn handle(&self, request: i32, chain: &HandlerChain<i32, i32>) -> Option<i32> {
47/// chain.handle(request + 1)
48/// }
49/// }
50///
51/// impl Handler<i32, i32> for Double {
52/// fn handle(&self, request: i32, _chain: &HandlerChain<i32, i32>) -> Option<i32> {
53/// Some(request * 2)
54/// }
55/// }
56///
57/// let chain = HandlerChain::create()
58/// .add_next(Box::new(Increment))
59/// .add_next(Box::new(Double));
60/// assert_eq!(chain.handle(3), Some(8));
61/// assert_eq!(chain.handle(3), None);
62/// ```
63///
64/// The cursor advances before each handler is called. Handlers delegate explicitly
65/// through [`Self::handle`]; returning a response without delegation stops that call.
66/// Later calls continue at the current cursor. Independent requests require an
67/// explicit [`Self::reset`] when reusing the chain.
68pub struct HandlerChain<T, R> {
69 /// List of handlers in the chain
70 handlers: Vec<Box<dyn Handler<T, R>>>,
71
72 /// Current position in the handler chain.
73 /// Uses Cell to achieve interior mutability, avoiding unsafe code.
74 current_index: Cell<usize>,
75}
76
77impl<T, R> HandlerChain<T, R> {
78 /// Create a new empty handler chain.
79 ///
80 /// # Returns
81 ///
82 /// A new `HandlerChain` instance with no handlers
83 ///
84 /// # Examples
85 ///
86 /// ```
87 /// use rocketmq_model::common::chain::HandlerChain;
88 ///
89 /// let chain = HandlerChain::<i32, i32>::create();
90 /// assert!(chain.is_empty());
91 /// assert_eq!(chain.handle(1), None);
92 /// ```
93 pub fn create() -> Self {
94 Self {
95 handlers: Vec::new(),
96 current_index: Cell::new(0),
97 }
98 }
99
100 /// Add a handler to the end of the chain.
101 ///
102 /// This method allows for builder-style chaining by returning `self`.
103 ///
104 /// # Arguments
105 ///
106 /// * `handler` - A boxed handler to add to the chain
107 ///
108 /// # Returns
109 ///
110 /// Self for method chaining
111 ///
112 /// See [`HandlerChain`] for a complete example with delegating and terminal handlers.
113 pub fn add_next(mut self, handler: Box<dyn Handler<T, R>>) -> Self {
114 self.handlers.push(handler);
115 self
116 }
117
118 /// Process the request through the handler chain.
119 ///
120 /// This method executes handlers in sequence. Each handler can process
121 /// the request and optionally call this method again to continue to the
122 /// next handler in the chain.
123 ///
124 /// # Arguments
125 ///
126 /// * `t` - The request to process
127 ///
128 /// # Returns
129 ///
130 /// An `Option<R>` containing the response, or `None` if no handlers
131 /// are left or no response is produced
132 ///
133 /// The cursor advances before invoking the selected handler. Returning a response
134 /// without calling `chain.handle` leaves later handlers for a subsequent call.
135 /// The cursor is not reset automatically, even if a handler returns `None`.
136 /// See [`HandlerChain`] for delegation and [`Self::reset`] for reuse.
137 pub fn handle(&self, t: T) -> Option<R> {
138 let index = self.current_index.get();
139 if index < self.handlers.len() {
140 // Update index (interior mutability)
141 self.current_index.set(index + 1);
142
143 // Now we can safely call the handler because current_index uses Cell
144 // No need to mutably borrow entire self
145 self.handlers[index].handle(t, self)
146 } else {
147 None
148 }
149 }
150
151 /// Reset the chain to start from the beginning.
152 ///
153 /// This allows reusing the same chain for multiple requests.
154 ///
155 /// # Examples
156 ///
157 /// ```
158 /// use rocketmq_model::common::chain::{Handler, HandlerChain};
159 ///
160 /// struct Echo;
161 /// impl Handler<i32, i32> for Echo {
162 /// fn handle(&self, request: i32, _chain: &HandlerChain<i32, i32>) -> Option<i32> {
163 /// Some(request)
164 /// }
165 /// }
166 ///
167 /// let mut chain = HandlerChain::create().add_next(Box::new(Echo));
168 /// assert_eq!(chain.handle(7), Some(7));
169 /// assert_eq!(chain.handle(8), None);
170 /// chain.reset();
171 /// assert_eq!(chain.handle(8), Some(8));
172 /// ```
173 pub fn reset(&mut self) {
174 self.current_index.set(0);
175 }
176
177 /// Get the number of handlers in the chain.
178 ///
179 /// # Returns
180 ///
181 /// The number of handlers
182 pub fn len(&self) -> usize {
183 self.handlers.len()
184 }
185
186 /// Check if the chain is empty.
187 ///
188 /// # Returns
189 ///
190 /// `true` if there are no handlers, `false` otherwise
191 pub fn is_empty(&self) -> bool {
192 self.handlers.is_empty()
193 }
194}
195
196impl<T, R> Default for HandlerChain<T, R> {
197 fn default() -> Self {
198 Self::create()
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use std::cell::RefCell;
205 use std::rc::Rc;
206
207 use super::*;
208
209 type Log = Rc<RefCell<Vec<&'static str>>>;
210
211 struct Delegate {
212 name: &'static str,
213 log: Log,
214 }
215
216 impl Handler<i32, i32> for Delegate {
217 fn handle(&self, request: i32, chain: &HandlerChain<i32, i32>) -> Option<i32> {
218 self.log.borrow_mut().push(self.name);
219 chain.handle(request + 1)
220 }
221 }
222
223 struct Terminal {
224 name: &'static str,
225 log: Log,
226 }
227
228 impl Handler<i32, i32> for Terminal {
229 fn handle(&self, request: i32, _chain: &HandlerChain<i32, i32>) -> Option<i32> {
230 self.log.borrow_mut().push(self.name);
231 Some(request * 10)
232 }
233 }
234
235 struct Silent {
236 name: &'static str,
237 log: Log,
238 }
239
240 impl Handler<i32, i32> for Silent {
241 fn handle(&self, _request: i32, _chain: &HandlerChain<i32, i32>) -> Option<i32> {
242 self.log.borrow_mut().push(self.name);
243 None
244 }
245 }
246
247 #[test]
248 fn empty_chain_returns_none() {
249 let chain = HandlerChain::<i32, i32>::create();
250 assert!(chain.is_empty());
251 assert_eq!(chain.len(), 0);
252 assert_eq!(chain.handle(1), None);
253 assert_eq!(chain.handle(2), None);
254 }
255
256 #[test]
257 fn terminal_first_handler_leaves_rest_for_next_call() {
258 let log = Log::default();
259 let chain = HandlerChain::create()
260 .add_next(Box::new(Terminal {
261 name: "first",
262 log: log.clone(),
263 }))
264 .add_next(Box::new(Terminal {
265 name: "second",
266 log: log.clone(),
267 }));
268
269 assert_eq!(chain.handle(1), Some(10));
270 assert_eq!(*log.borrow(), ["first"]);
271
272 assert_eq!(chain.handle(2), Some(20));
273 assert_eq!(*log.borrow(), ["first", "second"]);
274
275 assert_eq!(chain.handle(3), None);
276 assert_eq!(*log.borrow(), ["first", "second"]);
277 }
278
279 #[test]
280 fn delegating_handlers_run_in_order() {
281 let log = Log::default();
282 let chain = HandlerChain::create()
283 .add_next(Box::new(Delegate {
284 name: "a",
285 log: log.clone(),
286 }))
287 .add_next(Box::new(Delegate {
288 name: "b",
289 log: log.clone(),
290 }))
291 .add_next(Box::new(Terminal {
292 name: "c",
293 log: log.clone(),
294 }));
295
296 assert_eq!(chain.handle(1), Some(30));
297 assert_eq!(*log.borrow(), ["a", "b", "c"]);
298 assert_eq!(chain.handle(1), None);
299 }
300
301 #[test]
302 fn handler_returning_none_consumes_its_position() {
303 let log = Log::default();
304 let chain = HandlerChain::create()
305 .add_next(Box::new(Silent {
306 name: "silent",
307 log: log.clone(),
308 }))
309 .add_next(Box::new(Terminal {
310 name: "terminal",
311 log: log.clone(),
312 }));
313
314 assert_eq!(chain.handle(4), None);
315 assert_eq!(*log.borrow(), ["silent"]);
316
317 assert_eq!(chain.handle(4), Some(40));
318 assert_eq!(*log.borrow(), ["silent", "terminal"]);
319 }
320
321 #[test]
322 fn reset_replays_from_first_handler() {
323 let log = Log::default();
324 let mut chain = HandlerChain::create()
325 .add_next(Box::new(Terminal {
326 name: "first",
327 log: log.clone(),
328 }))
329 .add_next(Box::new(Terminal {
330 name: "second",
331 log: log.clone(),
332 }));
333
334 assert_eq!(chain.handle(1), Some(10));
335 assert_eq!(chain.handle(2), Some(20));
336 assert_eq!(chain.handle(3), None);
337
338 chain.reset();
339
340 assert_eq!(chain.handle(5), Some(50));
341 assert_eq!(*log.borrow(), ["first", "second", "first"]);
342 }
343}