Skip to main content

rocketmq_client_rust/consumer/consumer_impl/
consume_message_service.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
15use std::sync::Arc;
16
17use cheetah_string::CheetahString;
18use rocketmq_common::common::message::message_client_ext::MessageClientExt;
19use rocketmq_common::common::message::message_ext::MessageExt;
20use rocketmq_common::common::message::message_queue::MessageQueue;
21use rocketmq_remoting::protocol::body::consume_message_directly_result::ConsumeMessageDirectlyResult;
22use rocketmq_rust::ArcMut;
23use rocketmq_rust::WeakArcMut;
24
25use crate::consumer::consumer_impl::pop_process_queue::PopProcessQueue;
26use crate::consumer::consumer_impl::process_queue::ProcessQueue;
27use rocketmq_remoting::protocol::body::cm_result::CMResult;
28
29pub struct ConsumeMessageServiceGeneral<T, K> {
30    consume_message_concurrently_service: Option<ArcMut<T>>,
31    consume_message_orderly_service: Option<ArcMut<K>>,
32}
33impl<T, K> ConsumeMessageServiceGeneral<T, K> {
34    pub fn new(
35        consume_message_concurrently_service: Option<ArcMut<T>>,
36        consume_message_orderly_service: Option<ArcMut<K>>,
37    ) -> Self {
38        Self {
39            consume_message_concurrently_service,
40            consume_message_orderly_service,
41        }
42    }
43
44    pub fn get_consume_message_concurrently_service_weak(&self) -> Option<WeakArcMut<T>> {
45        self.consume_message_concurrently_service
46            .as_ref()
47            .map(ArcMut::downgrade)
48    }
49}
50
51impl<T, K> ConsumeMessageServiceGeneral<T, K>
52where
53    T: ConsumeMessageServiceTrait,
54    K: ConsumeMessageServiceTrait,
55{
56    pub fn start(&mut self) {
57        if let Some(consume_message_concurrently_service) = &mut self.consume_message_concurrently_service {
58            let this = consume_message_concurrently_service.clone();
59            consume_message_concurrently_service.start(this);
60        }
61
62        if let Some(consume_message_orderly_service) = &mut self.consume_message_orderly_service {
63            let this = consume_message_orderly_service.clone();
64            consume_message_orderly_service.start(this);
65        }
66    }
67
68    pub async fn shutdown(&mut self, await_terminate_millis: u64) {
69        if let Some(consume_message_concurrently_service) = &mut self.consume_message_concurrently_service {
70            consume_message_concurrently_service
71                .shutdown(await_terminate_millis)
72                .await;
73        }
74
75        if let Some(consume_message_orderly_service) = &mut self.consume_message_orderly_service {
76            consume_message_orderly_service.shutdown(await_terminate_millis).await;
77        }
78    }
79
80    pub fn update_core_pool_size(&self, core_pool_size: usize) {
81        if let Some(consume_message_concurrently_service) = &self.consume_message_concurrently_service {
82            consume_message_concurrently_service.update_core_pool_size(core_pool_size);
83        }
84
85        if let Some(consume_message_orderly_service) = &self.consume_message_orderly_service {
86            consume_message_orderly_service.update_core_pool_size(core_pool_size);
87        }
88    }
89
90    pub fn inc_core_pool_size(&self) {
91        if let Some(consume_message_concurrently_service) = &self.consume_message_concurrently_service {
92            consume_message_concurrently_service.inc_core_pool_size();
93        }
94
95        if let Some(consume_message_orderly_service) = &self.consume_message_orderly_service {
96            consume_message_orderly_service.inc_core_pool_size();
97        }
98    }
99
100    pub fn dec_core_pool_size(&self) {
101        if let Some(consume_message_concurrently_service) = &self.consume_message_concurrently_service {
102            consume_message_concurrently_service.dec_core_pool_size();
103        }
104
105        if let Some(consume_message_orderly_service) = &self.consume_message_orderly_service {
106            consume_message_orderly_service.dec_core_pool_size();
107        }
108    }
109
110    pub fn get_core_pool_size(&self) -> usize {
111        if let Some(consume_message_concurrently_service) = &self.consume_message_concurrently_service {
112            return consume_message_concurrently_service.get_core_pool_size();
113        }
114
115        if let Some(consume_message_orderly_service) = &self.consume_message_orderly_service {
116            return consume_message_orderly_service.get_core_pool_size();
117        }
118
119        num_cpus::get()
120    }
121
122    pub async fn consume_message_directly(
123        &self,
124        msg: MessageExt,
125        broker_name: Option<CheetahString>,
126    ) -> ConsumeMessageDirectlyResult {
127        if let Some(consume_message_concurrently_service) = &self.consume_message_concurrently_service {
128            let this = consume_message_concurrently_service.clone();
129            consume_message_concurrently_service
130                .consume_message_directly(msg, broker_name)
131                .await
132        } else if let Some(consume_message_orderly_service) = &self.consume_message_orderly_service {
133            let this = consume_message_orderly_service.clone();
134            consume_message_orderly_service
135                .consume_message_directly(msg, broker_name)
136                .await
137        } else {
138            ConsumeMessageDirectlyResult::new(
139                false,
140                true,
141                CMResult::CRThrowException,
142                CheetahString::from_static_str("ConsumeMessageServiceGeneral has no direct-consume service"),
143                0,
144            )
145        }
146    }
147
148    pub async fn submit_consume_request(
149        &self,
150        msgs: Vec<ArcMut<MessageExt>>,
151        process_queue: Arc<ProcessQueue>,
152        message_queue: MessageQueue,
153        dispatch_to_consume: bool,
154    ) {
155        if let Some(consume_message_concurrently_service) = &self.consume_message_concurrently_service {
156            let this = consume_message_concurrently_service.clone();
157            consume_message_concurrently_service
158                .submit_consume_request(this, msgs, process_queue, message_queue, dispatch_to_consume)
159                .await;
160        } else if let Some(consume_message_orderly_service) = &self.consume_message_orderly_service {
161            let this = consume_message_orderly_service.clone();
162            consume_message_orderly_service
163                .submit_consume_request(this, msgs, process_queue, message_queue, dispatch_to_consume)
164                .await;
165        }
166    }
167
168    pub async fn submit_pop_consume_request(
169        &self,
170        msgs: Vec<MessageExt>,
171        process_queue: &PopProcessQueue,
172        message_queue: &MessageQueue,
173    ) {
174        let _ = (msgs, process_queue, message_queue);
175    }
176
177    pub fn get_consume_message_concurrently_service(&self) -> Option<ArcMut<T>> {
178        self.consume_message_concurrently_service.as_ref().cloned()
179    }
180}
181
182pub struct ConsumeMessagePopServiceGeneral<T, K> {
183    consume_message_pop_concurrently_service: Option<ArcMut<T>>,
184    consume_message_pop_orderly_service: Option<ArcMut<K>>,
185}
186
187impl<T, K> ConsumeMessagePopServiceGeneral<T, K> {
188    pub fn new(
189        consume_message_pop_concurrently_service: Option<ArcMut<T>>,
190        consume_message_pop_orderly_service: Option<ArcMut<K>>,
191    ) -> Self {
192        Self {
193            consume_message_pop_concurrently_service,
194            consume_message_pop_orderly_service,
195        }
196    }
197}
198
199impl<T, K> ConsumeMessagePopServiceGeneral<T, K>
200where
201    T: ConsumeMessageServiceTrait,
202    K: ConsumeMessageServiceTrait,
203{
204    pub fn start(&mut self) {
205        if let Some(consume_message_pop_concurrently_service) = &mut self.consume_message_pop_concurrently_service {
206            let this = consume_message_pop_concurrently_service.clone();
207            consume_message_pop_concurrently_service.start(this);
208        }
209
210        if let Some(consume_message_pop_orderly_service) = &mut self.consume_message_pop_orderly_service {
211            let this = consume_message_pop_orderly_service.clone();
212            consume_message_pop_orderly_service.start(this);
213        }
214    }
215
216    pub async fn shutdown(&mut self, await_terminate_millis: u64) {
217        if let Some(consume_message_pop_concurrently_service) = &mut self.consume_message_pop_concurrently_service {
218            consume_message_pop_concurrently_service
219                .shutdown(await_terminate_millis)
220                .await;
221        }
222
223        if let Some(consume_message_pop_orderly_service) = &mut self.consume_message_pop_orderly_service {
224            consume_message_pop_orderly_service
225                .shutdown(await_terminate_millis)
226                .await;
227        }
228    }
229
230    pub fn update_core_pool_size(&self, core_pool_size: usize) {
231        if let Some(consume_message_pop_concurrently_service) = &self.consume_message_pop_concurrently_service {
232            consume_message_pop_concurrently_service.update_core_pool_size(core_pool_size);
233        }
234
235        if let Some(consume_message_pop_orderly_service) = &self.consume_message_pop_orderly_service {
236            consume_message_pop_orderly_service.update_core_pool_size(core_pool_size);
237        }
238    }
239
240    pub fn inc_core_pool_size(&self) {
241        if let Some(consume_message_pop_concurrently_service) = &self.consume_message_pop_concurrently_service {
242            consume_message_pop_concurrently_service.inc_core_pool_size();
243        }
244
245        if let Some(consume_message_pop_orderly_service) = &self.consume_message_pop_orderly_service {
246            consume_message_pop_orderly_service.inc_core_pool_size();
247        }
248    }
249
250    pub fn dec_core_pool_size(&self) {
251        if let Some(consume_message_pop_concurrently_service) = &self.consume_message_pop_concurrently_service {
252            consume_message_pop_concurrently_service.dec_core_pool_size();
253        }
254
255        if let Some(consume_message_pop_orderly_service) = &self.consume_message_pop_orderly_service {
256            consume_message_pop_orderly_service.dec_core_pool_size();
257        }
258    }
259
260    pub fn get_core_pool_size(&self) -> usize {
261        if let Some(consume_message_pop_concurrently_service) = &self.consume_message_pop_concurrently_service {
262            return consume_message_pop_concurrently_service.get_core_pool_size();
263        }
264
265        if let Some(consume_message_pop_orderly_service) = &self.consume_message_pop_orderly_service {
266            return consume_message_pop_orderly_service.get_core_pool_size();
267        }
268
269        num_cpus::get()
270    }
271
272    pub(crate) async fn consume_message_directly(
273        &self,
274        msg: MessageExt,
275        broker_name: Option<CheetahString>,
276    ) -> ConsumeMessageDirectlyResult {
277        if let Some(consume_message_pop_concurrently_service) = &self.consume_message_pop_concurrently_service {
278            let this = consume_message_pop_concurrently_service.clone();
279            consume_message_pop_concurrently_service
280                .consume_message_directly(msg, broker_name)
281                .await
282        } else if let Some(consume_message_pop_orderly_service) = &self.consume_message_pop_orderly_service {
283            let this = consume_message_pop_orderly_service.clone();
284            consume_message_pop_orderly_service
285                .consume_message_directly(msg, broker_name)
286                .await
287        } else {
288            ConsumeMessageDirectlyResult::new(
289                false,
290                true,
291                CMResult::CRThrowException,
292                CheetahString::from_static_str("ConsumeMessagePopServiceGeneral has no direct-consume service"),
293                0,
294            )
295        }
296    }
297
298    pub async fn submit_consume_request(
299        &self,
300        msgs: Vec<ArcMut<MessageClientExt>>,
301        process_queue: Arc<ProcessQueue>,
302        message_queue: MessageQueue,
303        dispatch_to_consume: bool,
304    ) {
305        let _ = (msgs, process_queue, message_queue, dispatch_to_consume);
306    }
307
308    pub async fn submit_pop_consume_request(
309        &self,
310        msgs: Vec<MessageExt>,
311        process_queue: &PopProcessQueue,
312        message_queue: &MessageQueue,
313    ) {
314        if let Some(consume_message_pop_concurrently_service) = &self.consume_message_pop_concurrently_service {
315            let this = consume_message_pop_concurrently_service.clone();
316            consume_message_pop_concurrently_service
317                .submit_pop_consume_request(this, msgs, process_queue, message_queue)
318                .await;
319        } else if let Some(consume_message_pop_orderly_service) = &self.consume_message_pop_orderly_service {
320            let this = consume_message_pop_orderly_service.clone();
321            consume_message_pop_orderly_service
322                .submit_pop_consume_request(this, msgs, process_queue, message_queue)
323                .await;
324        }
325    }
326}
327
328/// Trait defining the behavior of a message consumption service.
329#[allow(async_fn_in_trait)]
330pub trait ConsumeMessageServiceTrait {
331    /// Starts the message consumption service.
332    ///
333    /// # Arguments
334    ///
335    /// * `this` - An `ArcMut` reference to the service instance.
336    fn start(&mut self, this: ArcMut<Self>);
337
338    /// Shuts down the message consumption service.
339    ///
340    /// # Arguments
341    ///
342    /// * `await_terminate_millis` - The number of milliseconds to wait for termination.
343    async fn shutdown(&mut self, await_terminate_millis: u64);
344
345    /// Updates the core pool size of the service.
346    ///
347    /// # Arguments
348    ///
349    /// * `core_pool_size` - The new core pool size.
350    fn update_core_pool_size(&self, core_pool_size: usize) {}
351
352    /// Increases the core pool size of the service by one.
353    fn inc_core_pool_size(&self) {}
354
355    /// Decreases the core pool size of the service by one.
356    fn dec_core_pool_size(&self) {}
357
358    /// Gets the current core pool size of the service.
359    ///
360    /// # Returns
361    ///
362    /// The current core pool size.
363    fn get_core_pool_size(&self) -> usize {
364        num_cpus::get()
365    }
366
367    /// Consumes a message directly.
368    ///
369    /// # Arguments
370    ///
371    /// * `msg` - The message to be consumed.
372    /// * `broker_name` - An optional broker name.
373    ///
374    /// # Returns
375    ///
376    /// A `ConsumeMessageDirectlyResult` indicating the result of the consumption.
377    async fn consume_message_directly(
378        &self,
379        msg: MessageExt,
380        broker_name: Option<CheetahString>,
381    ) -> ConsumeMessageDirectlyResult;
382
383    /// Submits a consume request.
384    ///
385    /// # Arguments
386    ///
387    /// * `this` - An `ArcMut` reference to the service instance.
388    /// * `msgs` - A vector of messages to be consumed.
389    /// * `process_queue` - The process queue.
390    /// * `message_queue` - The message queue.
391    /// * `dispatch_to_consume` - A boolean indicating whether to dispatch to consume.
392    async fn submit_consume_request(
393        &self,
394        this: ArcMut<Self>,
395        msgs: Vec<ArcMut<MessageExt>>,
396        process_queue: Arc<ProcessQueue>,
397        message_queue: MessageQueue,
398        dispatch_to_consume: bool,
399    );
400
401    /// Submits a pop consume request.
402    ///
403    /// # Arguments
404    ///
405    /// * `msgs` - A vector of messages to be consumed.
406    /// * `process_queue` - The pop process queue.
407    /// * `message_queue` - The message queue.
408    async fn submit_pop_consume_request(
409        &self,
410        this: ArcMut<Self>,
411        msgs: Vec<MessageExt>,
412        process_queue: &PopProcessQueue,
413        message_queue: &MessageQueue,
414    );
415}
416
417/// Java-compatible public name for message consumption services.
418///
419/// Java exposes this contract as `ConsumeMessageService`. The original Rust
420/// implementation used `ConsumeMessageServiceTrait`; this blanket trait keeps
421/// existing implementors working while exposing the Java-equivalent API name.
422pub trait ConsumeMessageService: ConsumeMessageServiceTrait {}
423
424impl<T> ConsumeMessageService for T where T: ConsumeMessageServiceTrait + ?Sized {}
425
426#[cfg(test)]
427mod tests {
428    use super::*;
429
430    struct NoopConsumeMessageService;
431
432    impl ConsumeMessageServiceTrait for NoopConsumeMessageService {
433        fn start(&mut self, _this: ArcMut<Self>) {}
434
435        async fn shutdown(&mut self, _await_terminate_millis: u64) {}
436
437        async fn consume_message_directly(
438            &self,
439            _msg: MessageExt,
440            _broker_name: Option<CheetahString>,
441        ) -> ConsumeMessageDirectlyResult {
442            ConsumeMessageDirectlyResult::default()
443        }
444
445        async fn submit_consume_request(
446            &self,
447            _this: ArcMut<Self>,
448            _msgs: Vec<ArcMut<MessageExt>>,
449            _process_queue: Arc<ProcessQueue>,
450            _message_queue: MessageQueue,
451            _dispatch_to_consume: bool,
452        ) {
453        }
454
455        async fn submit_pop_consume_request(
456            &self,
457            _this: ArcMut<Self>,
458            _msgs: Vec<MessageExt>,
459            _process_queue: &PopProcessQueue,
460            _message_queue: &MessageQueue,
461        ) {
462        }
463    }
464
465    fn assert_consume_message_service<T: ConsumeMessageService>() {}
466
467    #[test]
468    fn consume_message_service_java_name_is_blanket_implemented() {
469        assert_consume_message_service::<NoopConsumeMessageService>();
470    }
471}