Skip to main content

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}