1use std::collections::HashMap;
16use std::sync::Arc;
17
18use cheetah_string::CheetahString;
19use rocketmq_common::common::consumer::consume_from_where::ConsumeFromWhere;
20use rocketmq_common::common::message::message_decoder;
21use rocketmq_common::common::message::message_ext::MessageExt;
22use rocketmq_common::common::message::message_queue::MessageQueue;
23use rocketmq_common::utils::util_all;
24use rocketmq_common::TimeUtils::current_millis;
25use rocketmq_remoting::protocol::body::consumer_running_info::ConsumerRunningInfo;
26use rocketmq_remoting::protocol::heartbeat::message_model::MessageModel;
27use rocketmq_remoting::protocol::namespace_util::NamespaceUtil;
28use rocketmq_remoting::runtime::RPCHook;
29use rocketmq_rust::ArcMut;
30
31use crate::base::client_config::ClientConfig;
32use crate::base::query_result::QueryResult;
33use crate::consumer::allocate_message_queue_strategy::AllocateMessageQueueStrategy;
34use crate::consumer::consumer_impl::default_mq_push_consumer_impl::DefaultMQPushConsumerImpl;
35use crate::consumer::default_mq_push_consumer_builder::DefaultMQPushConsumerBuilder;
36use crate::consumer::listener::message_listener::MessageListener;
37use crate::consumer::listener::message_listener_concurrently::MessageListenerConcurrently;
38use crate::consumer::listener::message_listener_orderly::MessageListenerOrderly;
39use crate::consumer::message_queue_listener::ArcMessageQueueListener;
40use crate::consumer::message_selector::MessageSelector;
41use crate::consumer::mq_consumer::MQConsumer;
42use crate::consumer::mq_consumer_inner::MQConsumerInner;
43use crate::consumer::mq_push_consumer::MQPushConsumer;
44use crate::consumer::rebalance_strategy::allocate_message_queue_averagely::AllocateMessageQueueAveragely;
45use crate::consumer::store::offset_store::OffsetStore;
46use crate::hook::consume_message_hook::ConsumeMessageHook;
47use crate::trace::async_trace_dispatcher::AsyncTraceDispatcher;
48use crate::trace::hook::consume_message_trace_hook_impl::ConsumeMessageTraceHookImpl;
49use crate::trace::trace_dispatcher::ArcTraceDispatcher;
50use crate::trace::trace_dispatcher::Type;
51
52#[derive(Clone)]
53pub struct ConsumerConfig {
54 pub(crate) consumer_group: CheetahString,
55 pub(crate) topic: CheetahString,
56 pub(crate) sub_expression: CheetahString,
57 pub(crate) message_model: MessageModel,
58 pub(crate) consume_from_where: ConsumeFromWhere,
59 pub(crate) consume_timestamp: Option<CheetahString>,
60 pub(crate) allocate_message_queue_strategy: Option<Arc<dyn AllocateMessageQueueStrategy>>,
61 pub(crate) subscription: ArcMut<HashMap<CheetahString, CheetahString>>,
63 pub(crate) message_listener: Option<ArcMut<MessageListener>>,
64 pub(crate) message_queue_listener: Option<ArcMessageQueueListener>,
65 pub(crate) offset_store: Option<ArcMut<OffsetStore>>,
66 pub(crate) consume_thread_min: u32,
67 pub(crate) consume_thread_max: u32,
68 pub(crate) adjust_thread_pool_nums_threshold: u64,
69 pub(crate) consume_concurrently_max_span: u32,
70 pub(crate) pull_threshold_for_queue: u32,
71 pub(crate) pop_threshold_for_queue: u32,
72 pub(crate) pull_threshold_size_for_queue: u32,
73 pub(crate) pull_threshold_for_topic: i32,
74 pub(crate) pull_threshold_size_for_topic: i32,
75 pub(crate) pull_interval: u64,
76 pub(crate) consume_message_batch_max_size: u32,
77 pub(crate) pull_batch_size: u32,
78 pub(crate) pull_batch_size_in_bytes: u32,
79 pub(crate) post_subscription_when_pull: bool,
80 pub(crate) unit_mode: bool,
81 pub(crate) max_reconsume_times: i32,
82 pub(crate) suspend_current_queue_time_millis: u64,
83 pub(crate) consume_timeout: u64,
84 pub(crate) pop_invisible_time: u64,
85 pub(crate) pop_batch_nums: u32,
86 pub(crate) await_termination_millis_when_shutdown: u64,
87 pub(crate) trace_dispatcher: Option<ArcTraceDispatcher>,
88 pub(crate) client_rebalance: bool,
89 pub(crate) rpc_hook: Option<Arc<dyn RPCHook>>,
90}
91
92impl ConsumerConfig {
93 pub fn consumer_group(&self) -> &CheetahString {
94 &self.consumer_group
95 }
96
97 pub fn message_model(&self) -> MessageModel {
98 self.message_model
99 }
100
101 pub fn consume_from_where(&self) -> ConsumeFromWhere {
102 self.consume_from_where
103 }
104
105 pub fn consume_timestamp(&self) -> &Option<CheetahString> {
106 &self.consume_timestamp
107 }
108
109 pub fn allocate_message_queue_strategy(&self) -> Option<Arc<dyn AllocateMessageQueueStrategy>> {
110 self.allocate_message_queue_strategy.clone()
111 }
112
113 pub fn subscription(&self) -> &ArcMut<HashMap<CheetahString, CheetahString>> {
114 &self.subscription
115 }
116
117 pub fn offset_store(&self) -> Option<ArcMut<OffsetStore>> {
126 self.offset_store.clone()
127 }
128
129 pub fn consume_thread_min(&self) -> u32 {
130 self.consume_thread_min
131 }
132
133 pub fn consume_thread_max(&self) -> u32 {
134 self.consume_thread_max
135 }
136
137 pub fn adjust_thread_pool_nums_threshold(&self) -> u64 {
138 self.adjust_thread_pool_nums_threshold
139 }
140
141 pub fn consume_concurrently_max_span(&self) -> u32 {
142 self.consume_concurrently_max_span
143 }
144
145 pub fn pull_threshold_for_queue(&self) -> u32 {
146 self.pull_threshold_for_queue
147 }
148
149 pub fn pop_threshold_for_queue(&self) -> u32 {
150 self.pop_threshold_for_queue
151 }
152
153 pub fn pull_threshold_size_for_queue(&self) -> u32 {
154 self.pull_threshold_size_for_queue
155 }
156
157 pub fn pull_threshold_for_topic(&self) -> i32 {
158 self.pull_threshold_for_topic
159 }
160
161 pub fn pull_threshold_size_for_topic(&self) -> i32 {
162 self.pull_threshold_size_for_topic
163 }
164
165 pub fn pull_interval(&self) -> u64 {
166 self.pull_interval
167 }
168
169 pub fn consume_message_batch_max_size(&self) -> u32 {
170 self.consume_message_batch_max_size
171 }
172
173 pub fn pull_batch_size(&self) -> u32 {
174 self.pull_batch_size
175 }
176
177 pub fn pull_batch_size_in_bytes(&self) -> u32 {
178 self.pull_batch_size_in_bytes
179 }
180
181 pub fn post_subscription_when_pull(&self) -> bool {
182 self.post_subscription_when_pull
183 }
184
185 pub fn unit_mode(&self) -> bool {
186 self.unit_mode
187 }
188
189 pub fn max_reconsume_times(&self) -> i32 {
190 self.max_reconsume_times
191 }
192
193 pub fn suspend_current_queue_time_millis(&self) -> u64 {
194 self.suspend_current_queue_time_millis
195 }
196
197 pub fn consume_timeout(&self) -> u64 {
198 self.consume_timeout
199 }
200
201 pub fn pop_invisible_time(&self) -> u64 {
202 self.pop_invisible_time
203 }
204
205 pub fn pop_batch_nums(&self) -> u32 {
206 self.pop_batch_nums
207 }
208
209 pub fn await_termination_millis_when_shutdown(&self) -> u64 {
210 self.await_termination_millis_when_shutdown
211 }
212
213 pub fn trace_dispatcher(&self) -> &Option<ArcTraceDispatcher> {
214 &self.trace_dispatcher
215 }
216
217 pub fn client_rebalance(&self) -> bool {
218 self.client_rebalance
219 }
220
221 pub fn rpc_hook(&self) -> &Option<Arc<dyn RPCHook>> {
222 &self.rpc_hook
223 }
224
225 pub fn set_consumer_group(&mut self, consumer_group: CheetahString) {
226 self.consumer_group = consumer_group;
227 }
228
229 pub fn set_message_model(&mut self, message_model: MessageModel) {
230 self.message_model = message_model;
231 }
232
233 pub fn set_consume_from_where(&mut self, consume_from_where: ConsumeFromWhere) {
234 self.consume_from_where = consume_from_where;
235 }
236
237 pub fn set_consume_timestamp(&mut self, consume_timestamp: Option<CheetahString>) {
238 self.consume_timestamp = consume_timestamp;
239 }
240
241 pub fn set_allocate_message_queue_strategy(
242 &mut self,
243 allocate_message_queue_strategy: Arc<dyn AllocateMessageQueueStrategy>,
244 ) {
245 self.allocate_message_queue_strategy = Some(allocate_message_queue_strategy);
246 }
247
248 pub fn set_subscription(&mut self, subscription: ArcMut<HashMap<CheetahString, CheetahString>>) {
253 self.subscription = subscription;
254 }
255
256 pub fn set_message_queue_listener(&mut self, message_queue_listener: Option<ArcMessageQueueListener>) {
264 self.message_queue_listener = message_queue_listener;
265 }
266
267 pub fn set_offset_store(&mut self, offset_store: Option<ArcMut<OffsetStore>>) {
268 self.offset_store = offset_store;
269 }
270
271 pub fn set_consume_thread_min(&mut self, consume_thread_min: u32) {
272 self.consume_thread_min = consume_thread_min;
273 }
274
275 pub fn set_consume_thread_max(&mut self, consume_thread_max: u32) {
276 self.consume_thread_max = consume_thread_max;
277 }
278
279 pub fn set_adjust_thread_pool_nums_threshold(&mut self, adjust_thread_pool_nums_threshold: u64) {
280 self.adjust_thread_pool_nums_threshold = adjust_thread_pool_nums_threshold;
281 }
282
283 pub fn set_consume_concurrently_max_span(&mut self, consume_concurrently_max_span: u32) {
284 self.consume_concurrently_max_span = consume_concurrently_max_span;
285 }
286
287 pub fn set_pull_threshold_for_queue(&mut self, pull_threshold_for_queue: u32) {
288 self.pull_threshold_for_queue = pull_threshold_for_queue;
289 }
290
291 pub fn set_pop_threshold_for_queue(&mut self, pop_threshold_for_queue: u32) {
292 self.pop_threshold_for_queue = pop_threshold_for_queue;
293 }
294
295 pub fn set_pull_threshold_size_for_queue(&mut self, pull_threshold_size_for_queue: u32) {
296 self.pull_threshold_size_for_queue = pull_threshold_size_for_queue;
297 }
298
299 pub fn set_pull_threshold_for_topic(&mut self, pull_threshold_for_topic: i32) {
300 self.pull_threshold_for_topic = pull_threshold_for_topic;
301 }
302
303 pub fn set_pull_threshold_size_for_topic(&mut self, pull_threshold_size_for_topic: i32) {
304 self.pull_threshold_size_for_topic = pull_threshold_size_for_topic;
305 }
306
307 pub fn set_pull_interval(&mut self, pull_interval: u64) {
308 self.pull_interval = pull_interval;
309 }
310
311 pub fn set_consume_message_batch_max_size(&mut self, consume_message_batch_max_size: u32) {
312 self.consume_message_batch_max_size = consume_message_batch_max_size;
313 }
314
315 pub fn set_pull_batch_size(&mut self, pull_batch_size: u32) {
316 self.pull_batch_size = pull_batch_size;
317 }
318
319 pub fn set_pull_batch_size_in_bytes(&mut self, pull_batch_size_in_bytes: u32) {
320 self.pull_batch_size_in_bytes = pull_batch_size_in_bytes;
321 }
322
323 pub fn set_post_subscription_when_pull(&mut self, post_subscription_when_pull: bool) {
324 self.post_subscription_when_pull = post_subscription_when_pull;
325 }
326
327 pub fn set_unit_mode(&mut self, unit_mode: bool) {
328 self.unit_mode = unit_mode;
329 }
330
331 pub fn set_max_reconsume_times(&mut self, max_reconsume_times: i32) {
332 self.max_reconsume_times = max_reconsume_times;
333 }
334
335 pub fn set_suspend_current_queue_time_millis(&mut self, suspend_current_queue_time_millis: u64) {
336 self.suspend_current_queue_time_millis = suspend_current_queue_time_millis;
337 }
338
339 pub fn set_consume_timeout(&mut self, consume_timeout: u64) {
340 self.consume_timeout = consume_timeout;
341 }
342
343 pub fn set_pop_invisible_time(&mut self, pop_invisible_time: u64) {
344 self.pop_invisible_time = pop_invisible_time;
345 }
346
347 pub fn set_pop_batch_nums(&mut self, pop_batch_nums: u32) {
348 self.pop_batch_nums = pop_batch_nums;
349 }
350
351 pub fn set_await_termination_millis_when_shutdown(&mut self, await_termination_millis_when_shutdown: u64) {
352 self.await_termination_millis_when_shutdown = await_termination_millis_when_shutdown;
353 }
354
355 pub fn set_trace_dispatcher(&mut self, trace_dispatcher: Option<ArcTraceDispatcher>) {
356 self.trace_dispatcher = trace_dispatcher;
357 }
358
359 pub fn set_client_rebalance(&mut self, client_rebalance: bool) {
360 self.client_rebalance = client_rebalance;
361 }
362
363 pub fn set_rpc_hook(&mut self, rpc_hook: Option<Arc<dyn RPCHook>>) {
364 self.rpc_hook = rpc_hook;
365 }
366}
367
368impl Default for ConsumerConfig {
369 fn default() -> Self {
370 ConsumerConfig {
371 consumer_group: CheetahString::new(),
372 topic: CheetahString::new(),
373 sub_expression: CheetahString::new(),
374 message_model: MessageModel::Clustering,
375 consume_from_where: ConsumeFromWhere::ConsumeFromLastOffset,
376 consume_timestamp: Some(CheetahString::from_string(util_all::time_millis_to_human_string3(
377 (current_millis() - (1000 * 60 * 30)) as i64,
378 ))),
379 allocate_message_queue_strategy: Some(Arc::new(AllocateMessageQueueAveragely)),
380 subscription: ArcMut::new(HashMap::new()),
381 message_listener: None,
382 message_queue_listener: None,
383 offset_store: None,
384
385 consume_thread_min: 20,
386 consume_thread_max: 64,
387 adjust_thread_pool_nums_threshold: 100_000,
388 consume_concurrently_max_span: 2000,
389 pull_threshold_for_queue: 1000,
390 pop_threshold_for_queue: 96,
391 pull_threshold_size_for_queue: 100,
392 pull_threshold_for_topic: -1,
393 pull_threshold_size_for_topic: -1,
394 pull_interval: 0,
395 consume_message_batch_max_size: 1,
396 pull_batch_size: 32,
397 pull_batch_size_in_bytes: 256 * 1024,
398 post_subscription_when_pull: false,
399 unit_mode: false,
400 max_reconsume_times: -1,
401 suspend_current_queue_time_millis: 1000,
402 consume_timeout: 15,
403 pop_invisible_time: 60000,
404 pop_batch_nums: 32,
405 await_termination_millis_when_shutdown: 0,
406 trace_dispatcher: None,
407 client_rebalance: true,
408 rpc_hook: None,
409 }
410 }
411}
412
413pub struct DefaultMQPushConsumer {
414 client_config: ClientConfig,
415 consumer_config: ArcMut<ConsumerConfig>,
416 pub(crate) default_mqpush_consumer_impl: Option<ArcMut<DefaultMQPushConsumerImpl>>,
417}
418
419impl MQConsumer for DefaultMQPushConsumer {
420 async fn create_topic(
421 &mut self,
422 key: &str,
423 new_topic: &str,
424 queue_num: i32,
425 attributes: HashMap<String, String>,
426 ) -> rocketmq_error::RocketMQResult<()> {
427 self.create_topic_with_flag(key, new_topic, queue_num, 0, attributes)
428 .await
429 }
430
431 async fn create_topic_with_flag(
432 &mut self,
433 key: &str,
434 new_topic: &str,
435 queue_num: i32,
436 topic_sys_flag: i32,
437 attributes: HashMap<String, String>,
438 ) -> rocketmq_error::RocketMQResult<()> {
439 let new_topic = self.client_config.with_namespace(CheetahString::from(new_topic));
440 self.default_mqpush_consumer_impl
441 .as_mut()
442 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?
443 .create_topic(key, new_topic.as_str(), queue_num, topic_sys_flag, attributes)
444 .await
445 }
446
447 async fn search_offset(&mut self, mq: &MessageQueue, timestamp: u64) -> rocketmq_error::RocketMQResult<i64> {
448 let mq = self.client_config.queue_with_namespace(mq.clone());
449 self.default_mqpush_consumer_impl
450 .as_mut()
451 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?
452 .search_offset(&mq, timestamp)
453 .await
454 }
455
456 async fn max_offset(&mut self, mq: &MessageQueue) -> rocketmq_error::RocketMQResult<i64> {
457 let mq = self.client_config.queue_with_namespace(mq.clone());
458 self.default_mqpush_consumer_impl
459 .as_mut()
460 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?
461 .max_offset(&mq)
462 .await
463 }
464
465 async fn min_offset(&mut self, mq: &MessageQueue) -> rocketmq_error::RocketMQResult<i64> {
466 let mq = self.client_config.queue_with_namespace(mq.clone());
467 self.default_mqpush_consumer_impl
468 .as_mut()
469 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?
470 .min_offset(&mq)
471 .await
472 }
473
474 async fn earliest_msg_store_time(&mut self, mq: &MessageQueue) -> rocketmq_error::RocketMQResult<i64> {
475 let mq = self.client_config.queue_with_namespace(mq.clone());
476 self.default_mqpush_consumer_impl
477 .as_mut()
478 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?
479 .earliest_msg_store_time(&mq)
480 .await
481 }
482
483 async fn query_message(
484 &mut self,
485 topic: &str,
486 key: &str,
487 max_num: i32,
488 begin: u64,
489 end: u64,
490 ) -> rocketmq_error::RocketMQResult<QueryResult> {
491 let topic = self.client_config.with_namespace(CheetahString::from(topic));
492 self.default_mqpush_consumer_impl
493 .as_mut()
494 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?
495 .query_message(topic.as_str(), key, max_num, begin, end)
496 .await
497 }
498
499 async fn view_message(&mut self, topic: &str, msg_id: &str) -> rocketmq_error::RocketMQResult<MessageExt> {
500 let topic = self.client_config.with_namespace(CheetahString::from(topic));
501 let consumer_impl = self
502 .default_mqpush_consumer_impl
503 .as_mut()
504 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?;
505 if message_decoder::decode_message_id(msg_id).is_ok() {
506 consumer_impl.view_message(topic.as_str(), msg_id).await
507 } else {
508 consumer_impl.query_message_by_uniq_key(topic.as_str(), msg_id).await
509 }
510 }
511
512 async fn send_message_back(
513 &mut self,
514 mut msg: MessageExt,
515 delay_level: i32,
516 broker_name: &str,
517 ) -> rocketmq_error::RocketMQResult<()> {
518 let consumer_impl = self
519 .default_mqpush_consumer_impl
520 .as_mut()
521 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?;
522 let topic = msg.topic().clone();
523 msg.set_topic(self.client_config.with_namespace(topic));
524 let broker_name = (!broker_name.is_empty()).then(|| CheetahString::from(broker_name));
525 consumer_impl
526 .send_message_back_with_broker_name(&mut msg, delay_level, broker_name, None)
527 .await
528 }
529
530 async fn fetch_subscribe_message_queues(
531 &mut self,
532 topic: &str,
533 ) -> rocketmq_error::RocketMQResult<Vec<MessageQueue>> {
534 let topic = self.client_config.with_namespace(CheetahString::from(topic));
535 let consumer_impl = self
536 .default_mqpush_consumer_impl
537 .as_mut()
538 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?;
539 consumer_impl.fetch_subscribe_message_queues(topic.as_str()).await
540 }
541}
542
543impl MQPushConsumer for DefaultMQPushConsumer {
544 async fn start(&mut self) -> rocketmq_error::RocketMQResult<()> {
545 let consumer_group = NamespaceUtil::wrap_namespace(
546 self.client_config.get_namespace().unwrap_or_default().as_str(),
547 self.consumer_config.consumer_group.as_str(),
548 );
549 self.set_consumer_group(consumer_group.as_str());
550 let consumer_impl = self
551 .default_mqpush_consumer_impl
552 .as_mut()
553 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?;
554 consumer_impl.start().await?;
555
556 let trace_dispatcher_to_start =
557 Self::prepare_trace_dispatcher(&self.client_config, &mut self.consumer_config, consumer_impl);
558 if let Some(dispatcher) = trace_dispatcher_to_start {
559 self.start_trace_dispatcher(dispatcher).await;
560 }
561
562 Ok(())
563 }
564
565 async fn shutdown(&mut self) {
566 if let Some(ref mut default_mqpush_consumer_impl) = self.default_mqpush_consumer_impl {
567 default_mqpush_consumer_impl
568 .shutdown(self.consumer_config.await_termination_millis_when_shutdown)
569 .await;
570 }
571 if let Some(ref trace_dispatcher) = self.consumer_config.trace_dispatcher {
572 trace_dispatcher.shutdown();
573 }
574 }
575
576 fn register_message_listener_concurrently<ML>(&mut self, message_listener: ML)
577 where
578 ML: MessageListenerConcurrently + Send + Sync + 'static,
579 {
580 let message_listener = MessageListener {
581 message_listener_concurrently: Some(Arc::new(message_listener)),
582 message_listener_orderly: None,
583 };
584 self.consumer_config.message_listener = Some(ArcMut::new(message_listener));
585 if let Some(default_mqpush_consumer_impl) = self.default_mqpush_consumer_impl.as_mut() {
586 default_mqpush_consumer_impl.register_message_listener(self.consumer_config.message_listener.clone());
587 } else {
588 tracing::warn!("DefaultMQPushConsumerImpl is not initialized; listener stored in consumer config");
589 }
590 }
591
592 fn register_message_listener_orderly<ML>(&mut self, message_listener: ML)
593 where
594 ML: MessageListenerOrderly + Send + Sync + 'static,
595 {
596 let message_listener = MessageListener {
597 message_listener_concurrently: None,
598 message_listener_orderly: Some(Arc::new(message_listener)),
599 };
600 self.consumer_config.message_listener = Some(ArcMut::new(message_listener));
601 if let Some(default_mqpush_consumer_impl) = self.default_mqpush_consumer_impl.as_mut() {
602 default_mqpush_consumer_impl.register_message_listener(self.consumer_config.message_listener.clone());
603 } else {
604 tracing::warn!("DefaultMQPushConsumerImpl is not initialized; listener stored in consumer config");
605 }
606 }
607
608 async fn subscribe(
609 &mut self,
610 topic: impl Into<CheetahString>,
611 sub_expression: impl Into<CheetahString>,
612 ) -> rocketmq_error::RocketMQResult<()> {
613 let topic = self.client_config.with_namespace(topic);
614 let sub_expression = sub_expression.into();
615
616 self.default_mqpush_consumer_impl
617 .as_mut()
618 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?
619 .subscribe(topic, sub_expression)
620 .await
621 }
622
623 async fn subscribe_with_selector(
624 &mut self,
625 topic: &str,
626 selector: Option<MessageSelector>,
627 ) -> rocketmq_error::RocketMQResult<()> {
628 let consumer_impl = self
629 .default_mqpush_consumer_impl
630 .as_mut()
631 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?;
632 let topic = self.client_config.with_namespace(CheetahString::from(topic));
633 consumer_impl.subscribe_with_selector(topic, selector).await
634 }
635
636 async fn unsubscribe(&mut self, topic: &str) {
637 if let Some(ref mut default_mqpush_consumer_impl) = self.default_mqpush_consumer_impl {
638 default_mqpush_consumer_impl.unsubscribe(topic).await;
639 }
640 }
641
642 async fn suspend(&self) {
643 if let Some(ref default_mqpush_consumer_impl) = self.default_mqpush_consumer_impl {
644 default_mqpush_consumer_impl.suspend().await;
645 }
646 }
647
648 async fn resume(&self) {
649 if let Some(ref default_mqpush_consumer_impl) = self.default_mqpush_consumer_impl {
650 default_mqpush_consumer_impl.resume().await;
651 }
652 }
653
654 fn update_core_pool_size(&self, core_pool_size: usize) -> rocketmq_error::RocketMQResult<()> {
655 let consumer_impl = self
656 .default_mqpush_consumer_impl
657 .as_ref()
658 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?;
659 consumer_impl.update_core_pool_size(core_pool_size);
660 Ok(())
661 }
662}
663
664impl DefaultMQPushConsumer {
665 pub fn builder() -> DefaultMQPushConsumerBuilder {
666 DefaultMQPushConsumerBuilder::default()
667 }
668
669 pub async fn start(&mut self) -> rocketmq_error::RocketMQResult<()> {
670 <Self as MQPushConsumer>::start(self).await
671 }
672
673 pub async fn shutdown(&mut self) {
674 <Self as MQPushConsumer>::shutdown(self).await;
675 }
676
677 pub async fn create_topic(
678 &mut self,
679 key: &str,
680 new_topic: &str,
681 queue_num: i32,
682 attributes: HashMap<String, String>,
683 ) -> rocketmq_error::RocketMQResult<()> {
684 <Self as MQConsumer>::create_topic(self, key, new_topic, queue_num, attributes).await
685 }
686
687 pub async fn create_topic_with_flag(
688 &mut self,
689 key: &str,
690 new_topic: &str,
691 queue_num: i32,
692 topic_sys_flag: i32,
693 attributes: HashMap<String, String>,
694 ) -> rocketmq_error::RocketMQResult<()> {
695 <Self as MQConsumer>::create_topic_with_flag(self, key, new_topic, queue_num, topic_sys_flag, attributes).await
696 }
697
698 pub async fn search_offset(&mut self, mq: &MessageQueue, timestamp: u64) -> rocketmq_error::RocketMQResult<i64> {
699 <Self as MQConsumer>::search_offset(self, mq, timestamp).await
700 }
701
702 pub async fn max_offset(&mut self, mq: &MessageQueue) -> rocketmq_error::RocketMQResult<i64> {
703 <Self as MQConsumer>::max_offset(self, mq).await
704 }
705
706 pub async fn min_offset(&mut self, mq: &MessageQueue) -> rocketmq_error::RocketMQResult<i64> {
707 <Self as MQConsumer>::min_offset(self, mq).await
708 }
709
710 pub async fn earliest_msg_store_time(&mut self, mq: &MessageQueue) -> rocketmq_error::RocketMQResult<i64> {
711 <Self as MQConsumer>::earliest_msg_store_time(self, mq).await
712 }
713
714 pub async fn query_message(
715 &mut self,
716 topic: &str,
717 key: &str,
718 max_num: i32,
719 begin: u64,
720 end: u64,
721 ) -> rocketmq_error::RocketMQResult<QueryResult> {
722 <Self as MQConsumer>::query_message(self, topic, key, max_num, begin, end).await
723 }
724
725 pub async fn view_message(&mut self, topic: &str, msg_id: &str) -> rocketmq_error::RocketMQResult<MessageExt> {
726 <Self as MQConsumer>::view_message(self, topic, msg_id).await
727 }
728
729 pub async fn send_message_back(
730 &mut self,
731 msg: MessageExt,
732 delay_level: i32,
733 broker_name: &str,
734 ) -> rocketmq_error::RocketMQResult<()> {
735 <Self as MQConsumer>::send_message_back(self, msg, delay_level, broker_name).await
736 }
737
738 pub async fn send_message_back_to_origin_broker(
739 &mut self,
740 msg: MessageExt,
741 delay_level: i32,
742 ) -> rocketmq_error::RocketMQResult<()> {
743 <Self as MQConsumer>::send_message_back_to_origin_broker(self, msg, delay_level).await
744 }
745
746 pub async fn fetch_subscribe_message_queues(
747 &mut self,
748 topic: &str,
749 ) -> rocketmq_error::RocketMQResult<Vec<MessageQueue>> {
750 <Self as MQConsumer>::fetch_subscribe_message_queues(self, topic).await
751 }
752
753 pub async fn subscribe(
754 &mut self,
755 topic: impl Into<CheetahString>,
756 sub_expression: impl Into<CheetahString>,
757 ) -> rocketmq_error::RocketMQResult<()> {
758 <Self as MQPushConsumer>::subscribe(self, topic, sub_expression).await
759 }
760
761 pub async fn subscribe_with_selector(
762 &mut self,
763 topic: &str,
764 selector: Option<MessageSelector>,
765 ) -> rocketmq_error::RocketMQResult<()> {
766 <Self as MQPushConsumer>::subscribe_with_selector(self, topic, selector).await
767 }
768
769 pub async fn unsubscribe(&mut self, topic: &str) {
770 <Self as MQPushConsumer>::unsubscribe(self, topic).await;
771 }
772
773 pub async fn suspend(&self) {
774 <Self as MQPushConsumer>::suspend(self).await;
775 }
776
777 pub async fn resume(&self) {
778 <Self as MQPushConsumer>::resume(self).await;
779 }
780
781 pub fn update_core_pool_size(&self, core_pool_size: usize) -> rocketmq_error::RocketMQResult<()> {
782 <Self as MQPushConsumer>::update_core_pool_size(self, core_pool_size)
783 }
784
785 pub async fn consumer_running_info(&self) -> rocketmq_error::RocketMQResult<ConsumerRunningInfo> {
787 let consumer_impl = self
788 .default_mqpush_consumer_impl
789 .as_ref()
790 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?;
791 Ok(MQConsumerInner::consumer_running_info(consumer_impl.as_ref()).await)
792 }
793
794 fn prepare_trace_dispatcher(
795 client_config: &ClientConfig,
796 consumer_config: &mut ArcMut<ConsumerConfig>,
797 consumer_impl: &mut ArcMut<DefaultMQPushConsumerImpl>,
798 ) -> Option<ArcTraceDispatcher> {
799 let dispatcher = match consumer_config.trace_dispatcher.clone() {
800 Some(dispatcher) => dispatcher,
801 None if client_config.enable_trace => {
802 let trace_topic = client_config
803 .trace_topic
804 .as_ref()
805 .map(|topic| topic.as_str())
806 .unwrap_or_default();
807 let dispatcher = AsyncTraceDispatcher::new(
808 consumer_config.consumer_group.as_str(),
809 Type::Consume,
810 client_config.trace_msg_batch_num,
811 trace_topic,
812 consumer_config.rpc_hook.clone(),
813 );
814 Arc::new(dispatcher)
815 }
816 None => return None,
817 };
818
819 if let Some(async_dispatcher) = dispatcher.as_any().downcast_ref::<AsyncTraceDispatcher>() {
820 async_dispatcher.set_host_consumer(consumer_impl.clone());
821 async_dispatcher.set_namespace_v2(client_config.namespace_v2.clone());
822 async_dispatcher.set_use_tls(client_config.use_tls);
823 }
824
825 consumer_config.trace_dispatcher = Some(dispatcher.clone());
826 consumer_impl.register_consume_message_hook(ConsumeMessageTraceHookImpl::new(dispatcher.clone()));
827 Some(dispatcher)
828 }
829
830 async fn start_trace_dispatcher(&self, dispatcher: ArcTraceDispatcher) {
831 let name_server_addr = self
832 .client_config
833 .namesrv_addr
834 .as_ref()
835 .map(|addr| addr.as_str())
836 .unwrap_or_default();
837 if let Err(error) = dispatcher.start(name_server_addr, self.client_config.access_channel) {
838 tracing::warn!("trace dispatcher start failed: {}", error);
839 }
840 }
841
842 pub fn is_pause(&self) -> bool {
846 self.default_mqpush_consumer_impl
847 .as_ref()
848 .is_some_and(|consumer_impl| consumer_impl.is_pause())
849 }
850
851 pub fn is_consume_orderly(&self) -> bool {
855 self.default_mqpush_consumer_impl
856 .as_ref()
857 .is_some_and(|consumer_impl| consumer_impl.is_consume_orderly())
858 }
859
860 pub fn register_consume_message_hook(
864 &mut self,
865 hook: impl ConsumeMessageHook + 'static,
866 ) -> rocketmq_error::RocketMQResult<()> {
867 let consumer_impl = self
868 .default_mqpush_consumer_impl
869 .as_mut()
870 .ok_or_else(|| rocketmq_error::RocketMQError::not_initialized("DefaultMQPushConsumerImpl"))?;
871 consumer_impl.register_consume_message_hook(hook);
872 Ok(())
873 }
874
875 pub fn default_mq_push_consumer_impl(&self) -> Option<&ArcMut<DefaultMQPushConsumerImpl>> {
876 self.default_mqpush_consumer_impl.as_ref()
877 }
878
879 pub fn get_default_mq_push_consumer_impl(&self) -> Option<&ArcMut<DefaultMQPushConsumerImpl>> {
880 self.default_mq_push_consumer_impl()
881 }
882
883 pub fn message_listener(&self) -> Option<ArcMut<MessageListener>> {
884 self.consumer_config.message_listener.clone()
885 }
886
887 pub fn get_message_listener(&self) -> Option<ArcMut<MessageListener>> {
888 self.message_listener()
889 }
890
891 pub fn set_message_listener(&mut self, message_listener: Option<ArcMut<MessageListener>>) {
892 self.consumer_config.message_listener = message_listener.clone();
893 if let Some(consumer_impl) = self.default_mqpush_consumer_impl.as_mut() {
894 consumer_impl.register_message_listener(message_listener);
895 }
896 }
897
898 pub fn register_message_listener(&mut self, message_listener: Option<ArcMut<MessageListener>>) {
899 self.set_message_listener(message_listener);
900 }
901
902 pub fn allocate_message_queue_strategy(&self) -> Option<Arc<dyn AllocateMessageQueueStrategy>> {
903 self.consumer_config.allocate_message_queue_strategy.clone()
904 }
905
906 pub fn get_allocate_message_queue_strategy(&self) -> Option<Arc<dyn AllocateMessageQueueStrategy>> {
907 self.allocate_message_queue_strategy()
908 }
909
910 pub fn set_allocate_message_queue_strategy(
911 &mut self,
912 allocate_message_queue_strategy: Arc<dyn AllocateMessageQueueStrategy>,
913 ) {
914 self.consumer_config
915 .set_allocate_message_queue_strategy(allocate_message_queue_strategy);
916 }
917
918 pub fn consume_concurrently_max_span(&self) -> u32 {
919 self.consumer_config.consume_concurrently_max_span
920 }
921
922 pub fn get_consume_concurrently_max_span(&self) -> u32 {
923 self.consume_concurrently_max_span()
924 }
925
926 pub fn set_consume_concurrently_max_span(&mut self, consume_concurrently_max_span: u32) {
927 self.consumer_config
928 .set_consume_concurrently_max_span(consume_concurrently_max_span);
929 }
930
931 pub fn consume_from_where(&self) -> ConsumeFromWhere {
932 self.consumer_config.consume_from_where
933 }
934
935 pub fn get_consume_from_where(&self) -> ConsumeFromWhere {
936 self.consume_from_where()
937 }
938
939 pub fn set_consume_from_where(&mut self, consume_from_where: ConsumeFromWhere) {
940 self.consumer_config.set_consume_from_where(consume_from_where);
941 }
942
943 pub fn consume_message_batch_max_size(&self) -> u32 {
944 self.consumer_config.consume_message_batch_max_size
945 }
946
947 pub fn get_consume_message_batch_max_size(&self) -> u32 {
948 self.consume_message_batch_max_size()
949 }
950
951 pub fn set_consume_message_batch_max_size(&mut self, consume_message_batch_max_size: u32) {
952 self.consumer_config
953 .set_consume_message_batch_max_size(consume_message_batch_max_size);
954 }
955
956 pub fn consumer_group(&self) -> &CheetahString {
957 &self.consumer_config.consumer_group
958 }
959
960 pub fn get_consumer_group(&self) -> &CheetahString {
961 self.consumer_group()
962 }
963
964 pub fn get_subscription(&self) -> &ArcMut<HashMap<CheetahString, CheetahString>> {
965 &self.consumer_config.subscription
966 }
967
968 #[inline]
969 pub fn set_consumer_group(&mut self, consumer_group: impl Into<CheetahString>) {
970 self.consumer_config.set_consumer_group(consumer_group.into());
971 }
972
973 pub fn consume_thread_max(&self) -> u32 {
974 self.consumer_config.consume_thread_max
975 }
976
977 pub fn get_consume_thread_max(&self) -> u32 {
978 self.consume_thread_max()
979 }
980
981 pub fn set_consume_thread_max(&mut self, consume_thread_max: u32) {
982 self.consumer_config.set_consume_thread_max(consume_thread_max);
983 }
984
985 pub fn consume_thread_min(&self) -> u32 {
986 self.consumer_config.consume_thread_min
987 }
988
989 pub fn get_consume_thread_min(&self) -> u32 {
990 self.consume_thread_min()
991 }
992
993 pub fn set_consume_thread_min(&mut self, consume_thread_min: u32) {
994 self.consumer_config.set_consume_thread_min(consume_thread_min);
995 }
996
997 pub fn message_model(&self) -> MessageModel {
998 self.consumer_config.message_model
999 }
1000
1001 pub fn get_message_model(&self) -> MessageModel {
1002 self.message_model()
1003 }
1004
1005 pub fn set_message_model(&mut self, message_model: MessageModel) {
1006 self.consumer_config.set_message_model(message_model);
1007 }
1008
1009 pub fn pull_batch_size(&self) -> u32 {
1010 self.consumer_config.pull_batch_size
1011 }
1012
1013 pub fn get_pull_batch_size(&self) -> u32 {
1014 self.pull_batch_size()
1015 }
1016
1017 pub fn set_pull_batch_size(&mut self, pull_batch_size: u32) {
1018 self.consumer_config.set_pull_batch_size(pull_batch_size);
1019 }
1020
1021 pub fn pull_interval(&self) -> u64 {
1022 self.consumer_config.pull_interval
1023 }
1024
1025 pub fn get_pull_interval(&self) -> u64 {
1026 self.pull_interval()
1027 }
1028
1029 pub fn set_pull_interval(&mut self, pull_interval: u64) {
1030 self.consumer_config.set_pull_interval(pull_interval);
1031 }
1032
1033 pub fn pull_threshold_for_queue(&self) -> u32 {
1034 self.consumer_config.pull_threshold_for_queue
1035 }
1036
1037 pub fn get_pull_threshold_for_queue(&self) -> u32 {
1038 self.pull_threshold_for_queue()
1039 }
1040
1041 pub fn set_pull_threshold_for_queue(&mut self, pull_threshold_for_queue: u32) {
1042 self.consumer_config
1043 .set_pull_threshold_for_queue(pull_threshold_for_queue);
1044 }
1045
1046 pub fn pop_threshold_for_queue(&self) -> u32 {
1047 self.consumer_config.pop_threshold_for_queue
1048 }
1049
1050 pub fn get_pop_threshold_for_queue(&self) -> u32 {
1051 self.pop_threshold_for_queue()
1052 }
1053
1054 pub fn set_pop_threshold_for_queue(&mut self, pop_threshold_for_queue: u32) {
1055 self.consumer_config
1056 .set_pop_threshold_for_queue(pop_threshold_for_queue);
1057 }
1058
1059 pub fn pull_threshold_for_topic(&self) -> i32 {
1060 self.consumer_config.pull_threshold_for_topic
1061 }
1062
1063 pub fn get_pull_threshold_for_topic(&self) -> i32 {
1064 self.pull_threshold_for_topic()
1065 }
1066
1067 pub fn set_pull_threshold_for_topic(&mut self, pull_threshold_for_topic: i32) {
1068 self.consumer_config
1069 .set_pull_threshold_for_topic(pull_threshold_for_topic);
1070 }
1071
1072 pub fn pull_threshold_size_for_queue(&self) -> u32 {
1073 self.consumer_config.pull_threshold_size_for_queue
1074 }
1075
1076 pub fn get_pull_threshold_size_for_queue(&self) -> u32 {
1077 self.pull_threshold_size_for_queue()
1078 }
1079
1080 pub fn set_pull_threshold_size_for_queue(&mut self, pull_threshold_size_for_queue: u32) {
1081 self.consumer_config
1082 .set_pull_threshold_size_for_queue(pull_threshold_size_for_queue);
1083 }
1084
1085 pub fn pull_threshold_size_for_topic(&self) -> i32 {
1086 self.consumer_config.pull_threshold_size_for_topic
1087 }
1088
1089 pub fn get_pull_threshold_size_for_topic(&self) -> i32 {
1090 self.pull_threshold_size_for_topic()
1091 }
1092
1093 pub fn set_pull_threshold_size_for_topic(&mut self, pull_threshold_size_for_topic: i32) {
1094 self.consumer_config
1095 .set_pull_threshold_size_for_topic(pull_threshold_size_for_topic);
1096 }
1097
1098 pub fn consume_timestamp(&self) -> Option<CheetahString> {
1099 self.consumer_config.consume_timestamp.clone()
1100 }
1101
1102 pub fn get_consume_timestamp(&self) -> Option<CheetahString> {
1103 self.consume_timestamp()
1104 }
1105
1106 pub fn set_consume_timestamp(&mut self, consume_timestamp: impl Into<CheetahString>) {
1107 self.consumer_config
1108 .set_consume_timestamp(Some(consume_timestamp.into()));
1109 }
1110
1111 pub fn clear_consume_timestamp(&mut self) {
1112 self.consumer_config.set_consume_timestamp(None);
1113 }
1114
1115 pub fn is_post_subscription_when_pull(&self) -> bool {
1116 self.consumer_config.post_subscription_when_pull
1117 }
1118
1119 pub fn set_post_subscription_when_pull(&mut self, post_subscription_when_pull: bool) {
1120 self.consumer_config
1121 .set_post_subscription_when_pull(post_subscription_when_pull);
1122 }
1123
1124 pub fn is_unit_mode(&self) -> bool {
1125 self.consumer_config.unit_mode
1126 }
1127
1128 pub fn set_unit_mode(&mut self, unit_mode: bool) {
1129 self.consumer_config.set_unit_mode(unit_mode);
1130 }
1131
1132 pub fn adjust_thread_pool_nums_threshold(&self) -> u64 {
1133 self.consumer_config.adjust_thread_pool_nums_threshold
1134 }
1135
1136 pub fn get_adjust_thread_pool_nums_threshold(&self) -> u64 {
1137 self.adjust_thread_pool_nums_threshold()
1138 }
1139
1140 pub fn set_adjust_thread_pool_nums_threshold(&mut self, adjust_thread_pool_nums_threshold: u64) {
1141 self.consumer_config
1142 .set_adjust_thread_pool_nums_threshold(adjust_thread_pool_nums_threshold);
1143 }
1144
1145 pub fn max_reconsume_times(&self) -> i32 {
1146 self.consumer_config.max_reconsume_times
1147 }
1148
1149 pub fn get_max_reconsume_times(&self) -> i32 {
1150 self.max_reconsume_times()
1151 }
1152
1153 pub fn set_max_reconsume_times(&mut self, max_reconsume_times: i32) {
1154 self.consumer_config.set_max_reconsume_times(max_reconsume_times);
1155 }
1156
1157 pub fn suspend_current_queue_time_millis(&self) -> u64 {
1158 self.consumer_config.suspend_current_queue_time_millis
1159 }
1160
1161 pub fn get_suspend_current_queue_time_millis(&self) -> u64 {
1162 self.suspend_current_queue_time_millis()
1163 }
1164
1165 pub fn set_suspend_current_queue_time_millis(&mut self, suspend_current_queue_time_millis: u64) {
1166 self.consumer_config
1167 .set_suspend_current_queue_time_millis(suspend_current_queue_time_millis);
1168 }
1169
1170 pub fn consume_timeout(&self) -> u64 {
1171 self.consumer_config.consume_timeout
1172 }
1173
1174 pub fn get_consume_timeout(&self) -> u64 {
1175 self.consume_timeout()
1176 }
1177
1178 pub fn set_consume_timeout(&mut self, consume_timeout: u64) {
1179 self.consumer_config.set_consume_timeout(consume_timeout);
1180 }
1181
1182 pub fn pop_invisible_time(&self) -> u64 {
1183 self.consumer_config.pop_invisible_time
1184 }
1185
1186 pub fn get_pop_invisible_time(&self) -> u64 {
1187 self.pop_invisible_time()
1188 }
1189
1190 pub fn set_pop_invisible_time(&mut self, pop_invisible_time: u64) {
1191 self.consumer_config.set_pop_invisible_time(pop_invisible_time);
1192 }
1193
1194 pub fn await_termination_millis_when_shutdown(&self) -> u64 {
1195 self.consumer_config.await_termination_millis_when_shutdown
1196 }
1197
1198 pub fn get_await_termination_millis_when_shutdown(&self) -> u64 {
1199 self.await_termination_millis_when_shutdown()
1200 }
1201
1202 pub fn set_await_termination_millis_when_shutdown(&mut self, await_termination_millis_when_shutdown: u64) {
1203 self.consumer_config
1204 .set_await_termination_millis_when_shutdown(await_termination_millis_when_shutdown);
1205 }
1206
1207 pub fn pull_batch_size_in_bytes(&self) -> u32 {
1208 self.consumer_config.pull_batch_size_in_bytes
1209 }
1210
1211 pub fn get_pull_batch_size_in_bytes(&self) -> u32 {
1212 self.pull_batch_size_in_bytes()
1213 }
1214
1215 pub fn set_pull_batch_size_in_bytes(&mut self, pull_batch_size_in_bytes: u32) {
1216 self.consumer_config
1217 .set_pull_batch_size_in_bytes(pull_batch_size_in_bytes);
1218 }
1219
1220 pub fn trace_dispatcher(&self) -> Option<ArcTraceDispatcher> {
1221 self.consumer_config.trace_dispatcher.clone()
1222 }
1223
1224 pub fn get_trace_dispatcher(&self) -> Option<ArcTraceDispatcher> {
1225 self.trace_dispatcher()
1226 }
1227
1228 pub fn is_use_tls(&self) -> bool {
1229 self.client_config.is_use_tls()
1230 }
1231
1232 pub fn set_use_tls(&mut self, use_tls: bool) {
1233 self.client_config.set_use_tls(use_tls);
1234 if let Some(consumer_impl) = self.default_mqpush_consumer_impl.as_mut() {
1235 consumer_impl.client_config.set_use_tls(use_tls);
1236 consumer_impl.rebalance_impl.client_config.set_use_tls(use_tls);
1237 }
1238 if let Some(trace_dispatcher) = self.consumer_config.trace_dispatcher.as_ref() {
1239 if let Some(async_dispatcher) = trace_dispatcher.as_any().downcast_ref::<AsyncTraceDispatcher>() {
1240 async_dispatcher.set_use_tls(use_tls);
1241 }
1242 }
1243 }
1244
1245 pub fn offset_store(&self) -> Option<ArcMut<OffsetStore>> {
1246 self.consumer_config.offset_store().or_else(|| {
1247 self.default_mqpush_consumer_impl
1248 .as_ref()
1249 .and_then(|consumer_impl| consumer_impl.offset_store())
1250 })
1251 }
1252
1253 pub fn get_offset_store(&self) -> Option<ArcMut<OffsetStore>> {
1254 self.offset_store()
1255 }
1256
1257 pub fn set_offset_store(&mut self, offset_store: Option<ArcMut<OffsetStore>>) {
1258 self.consumer_config.set_offset_store(offset_store.clone());
1259 if let Some(consumer_impl) = self.default_mqpush_consumer_impl.as_mut() {
1260 consumer_impl.set_offset_store(offset_store);
1261 }
1262 }
1263
1264 pub fn pop_batch_nums(&self) -> u32 {
1265 self.consumer_config.pop_batch_nums
1266 }
1267
1268 pub fn get_pop_batch_nums(&self) -> u32 {
1269 self.pop_batch_nums()
1270 }
1271
1272 pub fn set_pop_batch_nums(&mut self, pop_batch_nums: u32) {
1273 self.consumer_config.set_pop_batch_nums(pop_batch_nums);
1274 }
1275
1276 pub fn is_client_rebalance(&self) -> bool {
1277 self.consumer_config.client_rebalance
1278 }
1279
1280 pub fn set_client_rebalance(&mut self, client_rebalance: bool) {
1281 self.consumer_config.set_client_rebalance(client_rebalance);
1282 }
1283
1284 pub fn message_queue_listener(&self) -> Option<ArcMessageQueueListener> {
1285 self.consumer_config.message_queue_listener.clone()
1286 }
1287
1288 pub fn get_message_queue_listener(&self) -> Option<ArcMessageQueueListener> {
1289 self.message_queue_listener()
1290 }
1291
1292 pub fn set_message_queue_listener(&mut self, message_queue_listener: Option<ArcMessageQueueListener>) {
1293 self.consumer_config.set_message_queue_listener(message_queue_listener);
1294 }
1295
1296 pub fn new(client_config: ClientConfig, consumer_config: ConsumerConfig) -> DefaultMQPushConsumer {
1297 let consumer_config = ArcMut::new(consumer_config);
1298 let mut default_mqpush_consumer_impl = ArcMut::new(DefaultMQPushConsumerImpl::new(
1299 client_config.clone(),
1300 consumer_config.clone(),
1301 consumer_config.rpc_hook.clone(),
1302 ));
1303 let wrapper = default_mqpush_consumer_impl.clone();
1304 default_mqpush_consumer_impl.set_default_mqpush_consumer_impl(wrapper);
1305 DefaultMQPushConsumer {
1306 client_config,
1307 consumer_config,
1308 default_mqpush_consumer_impl: Some(default_mqpush_consumer_impl),
1309 }
1310 }
1311
1312 pub fn set_name_server_addr(&mut self, name_server_addr: CheetahString) {
1313 self.client_config.namesrv_addr = Some(name_server_addr);
1314 self.client_config
1315 .namespace_initialized
1316 .store(false, std::sync::atomic::Ordering::Release);
1317 }
1318}
1319
1320#[cfg(test)]
1321mod tests {
1322 use std::any::Any;
1323 use std::collections::HashSet;
1324 use std::sync::atomic::AtomicUsize;
1325 use std::sync::atomic::Ordering;
1326 use std::sync::Arc;
1327 use std::sync::Mutex as StdMutex;
1328
1329 use super::*;
1330 use crate::base::access_channel::AccessChannel;
1331 use crate::consumer::listener::consume_concurrently_context::ConsumeConcurrentlyContext;
1332 use crate::consumer::listener::consume_concurrently_status::ConsumeConcurrentlyStatus;
1333 use crate::consumer::message_queue_listener::MessageQueueListener;
1334 use crate::consumer::mq_consumer_inner::MQConsumerInner;
1335 use crate::consumer::store::read_offset_type::ReadOffsetType;
1336 use crate::hook::consume_message_context::ConsumeMessageContext;
1337 use crate::hook::consume_message_hook::ConsumeMessageHook;
1338 use crate::trace::trace_dispatcher::TraceDispatcher;
1339
1340 #[derive(Default)]
1341 struct CapturingTraceDispatcher {
1342 start_count: AtomicUsize,
1343 shutdown_count: AtomicUsize,
1344 append_count: AtomicUsize,
1345 last_name_srv_addr: StdMutex<Option<String>>,
1346 last_access_channel: StdMutex<Option<AccessChannel>>,
1347 }
1348
1349 impl TraceDispatcher for CapturingTraceDispatcher {
1350 fn start(&self, name_srv_addr: &str, access_channel: AccessChannel) -> rocketmq_error::RocketMQResult<()> {
1351 self.start_count.fetch_add(1, Ordering::SeqCst);
1352 *self.last_name_srv_addr.lock().expect("name server lock") = Some(name_srv_addr.to_string());
1353 *self.last_access_channel.lock().expect("access channel lock") = Some(access_channel);
1354 Ok(())
1355 }
1356
1357 fn append(&self, _ctx: &dyn Any) -> bool {
1358 self.append_count.fetch_add(1, Ordering::SeqCst);
1359 true
1360 }
1361
1362 fn flush(&self) -> rocketmq_error::RocketMQResult<()> {
1363 Ok(())
1364 }
1365
1366 fn shutdown(&self) {
1367 self.shutdown_count.fetch_add(1, Ordering::SeqCst);
1368 }
1369
1370 fn as_any(&self) -> &dyn Any {
1371 self
1372 }
1373
1374 fn as_mut_any(&mut self) -> &mut dyn Any {
1375 self
1376 }
1377 }
1378
1379 struct TestConcurrentListener;
1380
1381 impl MessageListenerConcurrently for TestConcurrentListener {
1382 fn consume_message(
1383 &self,
1384 _msgs: &[&MessageExt],
1385 _context: &ConsumeConcurrentlyContext,
1386 ) -> rocketmq_error::RocketMQResult<ConsumeConcurrentlyStatus> {
1387 Ok(ConsumeConcurrentlyStatus::ConsumeSuccess)
1388 }
1389 }
1390
1391 struct TestConsumeHook;
1392
1393 impl ConsumeMessageHook for TestConsumeHook {
1394 fn hook_name(&self) -> &'static str {
1395 "TestConsumeHook"
1396 }
1397
1398 fn consume_message_before(&self, _context: &mut ConsumeMessageContext) {}
1399
1400 fn consume_message_after(&self, _context: &mut ConsumeMessageContext) {}
1401 }
1402
1403 struct TestMessageQueueListener;
1404
1405 impl MessageQueueListener for TestMessageQueueListener {
1406 fn message_queue_changed(
1407 &self,
1408 _topic: &str,
1409 _mq_all: &HashSet<MessageQueue>,
1410 _mq_assigned: &HashSet<MessageQueue>,
1411 ) {
1412 }
1413 }
1414
1415 fn namespaced_push_consumer() -> DefaultMQPushConsumer {
1416 let mut client_config = ClientConfig::default();
1417 client_config.set_namespace(CheetahString::from_static_str("ns"));
1418
1419 DefaultMQPushConsumer::builder()
1420 .consumer_group("push_namespace_group")
1421 .client_config(client_config)
1422 .build()
1423 }
1424
1425 #[test]
1426 fn builder_preserves_default_allocate_message_queue_strategy() {
1427 let consumer = DefaultMQPushConsumer::builder()
1428 .consumer_group("builder_default_strategy_group")
1429 .build();
1430
1431 let strategy = consumer
1432 .consumer_config
1433 .allocate_message_queue_strategy
1434 .as_ref()
1435 .expect("default allocation strategy should be preserved");
1436 assert_eq!("AVG", strategy.get_name());
1437 }
1438
1439 #[tokio::test]
1440 async fn subscribe_without_impl_returns_not_initialized_error() {
1441 let mut consumer = DefaultMQPushConsumer::builder()
1442 .consumer_group("push_missing_impl_group")
1443 .build();
1444 consumer.default_mqpush_consumer_impl = None;
1445
1446 let error = consumer
1447 .subscribe("topic", "*")
1448 .await
1449 .expect_err("subscribe without impl should fail");
1450
1451 assert!(error.to_string().contains("DefaultMQPushConsumerImpl"));
1452 }
1453
1454 #[tokio::test]
1455 async fn mq_admin_facade_without_impl_returns_not_initialized_error() {
1456 let mut consumer = DefaultMQPushConsumer::builder()
1457 .consumer_group("push_missing_admin_impl_group")
1458 .build();
1459 consumer.default_mqpush_consumer_impl = None;
1460 let mq = MessageQueue::from_parts("TopicA", "broker-a", 0);
1461
1462 let max_error = MQConsumer::max_offset(&mut consumer, &mq)
1463 .await
1464 .expect_err("maxOffset without impl should fail");
1465 let query_error = MQConsumer::query_message(&mut consumer, "TopicA", "KeyA", 32, 0, 1)
1466 .await
1467 .expect_err("queryMessage without impl should fail");
1468 let view_error = MQConsumer::view_message(&mut consumer, "TopicA", "bad-msg-id")
1469 .await
1470 .expect_err("viewMessage without impl should fail");
1471
1472 assert!(max_error.to_string().contains("DefaultMQPushConsumerImpl"));
1473 assert!(query_error.to_string().contains("DefaultMQPushConsumerImpl"));
1474 assert!(view_error.to_string().contains("DefaultMQPushConsumerImpl"));
1475 }
1476
1477 #[tokio::test]
1478 async fn consumer_running_info_without_impl_returns_not_initialized_error() {
1479 let mut consumer = DefaultMQPushConsumer::builder()
1480 .consumer_group("push_missing_running_info_impl_group")
1481 .build();
1482 consumer.default_mqpush_consumer_impl = None;
1483
1484 let error = consumer
1485 .consumer_running_info()
1486 .await
1487 .expect_err("running info without impl should fail");
1488
1489 assert!(error.to_string().contains("DefaultMQPushConsumerImpl"));
1490 }
1491
1492 #[tokio::test]
1493 async fn consumer_running_info_facade_returns_impl_snapshot_like_java_admin() {
1494 let mut consumer = DefaultMQPushConsumer::builder()
1495 .consumer_group("push_running_info_group")
1496 .consume_thread_min(7)
1497 .consume_thread_max(11)
1498 .pull_batch_size(13)
1499 .consume_message_batch_max_size(3)
1500 .build();
1501
1502 consumer
1503 .subscribe("TopicRunningInfo", "TagA")
1504 .await
1505 .expect("subscribe should update running-info subscriptions");
1506
1507 let info = consumer
1508 .consumer_running_info()
1509 .await
1510 .expect("running info facade should delegate to impl");
1511
1512 assert_eq!(
1513 info.properties
1514 .get(ConsumerRunningInfo::PROP_CONSUME_TYPE)
1515 .map(String::as_str),
1516 Some("CONSUME_PASSIVELY")
1517 );
1518 assert_eq!(
1519 info.properties
1520 .get(ConsumerRunningInfo::PROP_THREADPOOL_CORE_SIZE)
1521 .map(String::as_str),
1522 Some("7")
1523 );
1524 assert_eq!(info.properties.get("consumeThreadMax").map(String::as_str), Some("11"));
1525 assert_eq!(info.properties.get("pullBatchSize").map(String::as_str), Some("13"));
1526 assert!(info
1527 .subscription_set
1528 .iter()
1529 .any(|subscription| subscription.topic.as_str() == "TopicRunningInfo"
1530 && subscription.sub_string.as_str() == "TagA"));
1531 }
1532
1533 #[test]
1534 fn register_listener_without_impl_stores_listener_without_panic() {
1535 let mut consumer = DefaultMQPushConsumer::builder()
1536 .consumer_group("push_missing_impl_group")
1537 .build();
1538 consumer.default_mqpush_consumer_impl = None;
1539
1540 consumer.register_message_listener_concurrently(TestConcurrentListener);
1541
1542 assert!(consumer.consumer_config.message_listener.is_some());
1543 }
1544
1545 #[test]
1546 fn push_message_listener_facade_syncs_config_and_impl_like_java() {
1547 let mut consumer = DefaultMQPushConsumer::builder()
1548 .consumer_group("push_listener_facade_group")
1549 .build();
1550 let listener = ArcMut::new(MessageListener::new(Some(Arc::new(TestConcurrentListener)), None));
1551
1552 assert!(consumer.default_mq_push_consumer_impl().is_some());
1553 assert!(consumer.message_listener().is_none());
1554
1555 consumer.set_message_listener(Some(listener.clone()));
1556
1557 assert!(consumer
1558 .message_listener()
1559 .expect("listener should be set")
1560 .is_concurrently());
1561 assert!(consumer
1562 .consumer_config
1563 .message_listener
1564 .as_ref()
1565 .expect("config listener should be set")
1566 .is_concurrently());
1567
1568 consumer.register_message_listener(None);
1569
1570 assert!(consumer.message_listener().is_none());
1571 assert!(consumer.consumer_config.message_listener.is_none());
1572 }
1573
1574 #[test]
1575 fn push_use_tls_facade_updates_impl_config_like_java() {
1576 let mut consumer = DefaultMQPushConsumer::builder()
1577 .consumer_group("push_tls_facade_group")
1578 .build();
1579
1580 assert!(!consumer.is_use_tls());
1581
1582 consumer.set_use_tls(true);
1583
1584 assert!(consumer.is_use_tls());
1585 let consumer_impl = consumer
1586 .default_mqpush_consumer_impl
1587 .as_ref()
1588 .expect("push consumer impl should exist");
1589 assert!(consumer_impl.client_config.is_use_tls());
1590 assert!(consumer_impl.rebalance_impl.client_config.is_use_tls());
1591 }
1592
1593 #[test]
1594 fn push_java_getter_aliases_delegate_to_config() {
1595 let mut consumer = DefaultMQPushConsumer::builder()
1596 .consumer_group("push_java_getter_group")
1597 .build();
1598 let offset_store = ArcMut::new(OffsetStore::new_test());
1599
1600 consumer.set_message_model(MessageModel::Broadcasting);
1601 consumer.set_consume_from_where(ConsumeFromWhere::ConsumeFromFirstOffset);
1602 consumer.set_consume_timestamp("20260101000000");
1603 consumer.set_consume_thread_min(8);
1604 consumer.set_consume_thread_max(16);
1605 consumer.set_consume_concurrently_max_span(321);
1606 consumer.set_consume_message_batch_max_size(7);
1607 consumer.set_pull_batch_size(11);
1608 consumer.set_pull_interval(13);
1609 consumer.set_pull_threshold_for_queue(17);
1610 consumer.set_pull_threshold_for_topic(19);
1611 consumer.set_pull_threshold_size_for_queue(23);
1612 consumer.set_pull_threshold_size_for_topic(29);
1613 consumer.set_consume_timeout(31);
1614 consumer.set_offset_store(Some(offset_store));
1615
1616 assert!(consumer.get_allocate_message_queue_strategy().is_some());
1617 assert_eq!(consumer.get_message_model(), MessageModel::Broadcasting);
1618 assert_eq!(
1619 consumer.get_consume_from_where(),
1620 ConsumeFromWhere::ConsumeFromFirstOffset
1621 );
1622 assert_eq!(
1623 consumer.get_consume_timestamp(),
1624 Some(CheetahString::from_static_str("20260101000000"))
1625 );
1626 assert_eq!(consumer.get_consume_thread_min(), 8);
1627 assert_eq!(consumer.get_consume_thread_max(), 16);
1628 assert_eq!(consumer.get_consume_concurrently_max_span(), 321);
1629 assert_eq!(consumer.get_consume_message_batch_max_size(), 7);
1630 assert_eq!(consumer.get_pull_batch_size(), 11);
1631 assert_eq!(consumer.get_pull_interval(), 13);
1632 assert_eq!(consumer.get_pull_threshold_for_queue(), 17);
1633 assert_eq!(consumer.get_pull_threshold_for_topic(), 19);
1634 assert_eq!(consumer.get_pull_threshold_size_for_queue(), 23);
1635 assert_eq!(consumer.get_pull_threshold_size_for_topic(), 29);
1636 assert_eq!(consumer.get_consume_timeout(), 31);
1637 assert!(consumer.get_offset_store().is_some());
1638 assert!(consumer.get_subscription().is_empty());
1639 }
1640
1641 #[tokio::test]
1642 async fn push_offset_store_facade_updates_impl_like_java_start_source() {
1643 let mut consumer = DefaultMQPushConsumer::builder()
1644 .consumer_group("push_offset_store_facade_group")
1645 .build();
1646 let offset_store = ArcMut::new(OffsetStore::new_test());
1647 let mq = MessageQueue::from_parts("TopicOffset", "broker-a", 0);
1648
1649 assert!(consumer.offset_store().is_none());
1650
1651 consumer.set_offset_store(Some(offset_store.clone()));
1652 offset_store.update_offset(&mq, 42, false).await;
1653
1654 assert_eq!(
1655 consumer
1656 .offset_store()
1657 .expect("facade offset store should be present")
1658 .read_offset(&mq, ReadOffsetType::ReadFromMemory)
1659 .await,
1660 42
1661 );
1662 assert_eq!(
1663 consumer
1664 .default_mqpush_consumer_impl
1665 .as_ref()
1666 .expect("push consumer impl should exist")
1667 .offset_store()
1668 .expect("impl offset store should be present")
1669 .read_offset(&mq, ReadOffsetType::ReadFromMemory)
1670 .await,
1671 42
1672 );
1673
1674 consumer.set_offset_store(None);
1675 assert!(consumer.offset_store().is_none());
1676 assert!(consumer
1677 .default_mqpush_consumer_impl
1678 .as_ref()
1679 .expect("push consumer impl should exist")
1680 .offset_store()
1681 .is_none());
1682 }
1683
1684 #[test]
1685 fn register_consume_message_hook_facade_updates_impl_like_java() {
1686 let mut consumer = DefaultMQPushConsumer::builder()
1687 .consumer_group("push_hook_group")
1688 .build();
1689
1690 consumer
1691 .register_consume_message_hook(TestConsumeHook)
1692 .expect("hook registration should succeed");
1693
1694 assert_eq!(
1695 consumer
1696 .default_mqpush_consumer_impl
1697 .as_ref()
1698 .expect("push consumer impl should exist")
1699 .consume_message_hook_count(),
1700 1
1701 );
1702 }
1703
1704 #[test]
1705 fn register_consume_message_hook_without_impl_returns_typed_error() {
1706 let mut consumer = DefaultMQPushConsumer::builder()
1707 .consumer_group("push_missing_impl_hook_group")
1708 .build();
1709 consumer.default_mqpush_consumer_impl = None;
1710
1711 let error = consumer
1712 .register_consume_message_hook(TestConsumeHook)
1713 .expect_err("hook registration without impl should fail");
1714
1715 assert!(error.to_string().contains("DefaultMQPushConsumerImpl"));
1716 }
1717
1718 #[test]
1719 fn push_runtime_config_facade_updates_shared_impl_config_like_java() {
1720 let mut consumer = DefaultMQPushConsumer::builder()
1721 .consumer_group("push_runtime_config_group")
1722 .build();
1723 let listener: ArcMessageQueueListener = Arc::new(TestMessageQueueListener);
1724
1725 consumer.set_allocate_message_queue_strategy(Arc::new(AllocateMessageQueueAveragely));
1726 consumer.set_consume_concurrently_max_span(1234);
1727 consumer.set_consume_from_where(ConsumeFromWhere::ConsumeFromFirstOffset);
1728 consumer.set_consume_message_batch_max_size(8);
1729 consumer.set_consumer_group("push_runtime_config_group_updated");
1730 consumer.set_consume_thread_max(48);
1731 consumer.set_consume_thread_min(12);
1732 consumer.set_message_model(MessageModel::Broadcasting);
1733 consumer.set_pull_batch_size(64);
1734 consumer.set_pull_interval(15);
1735 consumer.set_pull_threshold_for_queue(2048);
1736 consumer.set_pop_threshold_for_queue(128);
1737 consumer.set_pull_threshold_for_topic(4096);
1738 consumer.set_pull_threshold_size_for_queue(256);
1739 consumer.set_pull_threshold_size_for_topic(512);
1740 consumer.set_consume_timestamp("20260610101010");
1741 consumer.set_post_subscription_when_pull(true);
1742 consumer.set_unit_mode(true);
1743 consumer.set_adjust_thread_pool_nums_threshold(222_222);
1744 consumer.set_max_reconsume_times(19);
1745 consumer.set_suspend_current_queue_time_millis(3333);
1746 consumer.set_consume_timeout(44);
1747 consumer.set_pop_invisible_time(55_555);
1748 consumer.set_await_termination_millis_when_shutdown(66_666);
1749 consumer.set_pull_batch_size_in_bytes(512 * 1024);
1750 consumer.set_pop_batch_nums(16);
1751 consumer.set_client_rebalance(false);
1752 consumer.set_message_queue_listener(Some(listener));
1753
1754 assert_eq!(consumer.consume_concurrently_max_span(), 1234);
1755 assert_eq!(consumer.consume_from_where(), ConsumeFromWhere::ConsumeFromFirstOffset);
1756 assert_eq!(consumer.consume_message_batch_max_size(), 8);
1757 assert_eq!(consumer.consumer_group().as_str(), "push_runtime_config_group_updated");
1758 assert_eq!(consumer.consume_thread_max(), 48);
1759 assert_eq!(consumer.consume_thread_min(), 12);
1760 assert_eq!(consumer.message_model(), MessageModel::Broadcasting);
1761 assert_eq!(consumer.pull_batch_size(), 64);
1762 assert_eq!(consumer.pull_interval(), 15);
1763 assert_eq!(consumer.pull_threshold_for_queue(), 2048);
1764 assert_eq!(consumer.pop_threshold_for_queue(), 128);
1765 assert_eq!(consumer.pull_threshold_for_topic(), 4096);
1766 assert_eq!(consumer.pull_threshold_size_for_queue(), 256);
1767 assert_eq!(consumer.pull_threshold_size_for_topic(), 512);
1768 assert_eq!(
1769 consumer.consume_timestamp().as_ref().map(CheetahString::as_str),
1770 Some("20260610101010")
1771 );
1772 assert!(consumer.is_post_subscription_when_pull());
1773 assert!(consumer.is_unit_mode());
1774 assert_eq!(consumer.adjust_thread_pool_nums_threshold(), 222_222);
1775 assert_eq!(consumer.max_reconsume_times(), 19);
1776 assert_eq!(consumer.suspend_current_queue_time_millis(), 3333);
1777 assert_eq!(consumer.consume_timeout(), 44);
1778 assert_eq!(consumer.pop_invisible_time(), 55_555);
1779 assert_eq!(consumer.await_termination_millis_when_shutdown(), 66_666);
1780 assert_eq!(consumer.pull_batch_size_in_bytes(), 512 * 1024);
1781 assert_eq!(consumer.pop_batch_nums(), 16);
1782 assert!(!consumer.is_client_rebalance());
1783 assert!(consumer.message_queue_listener().is_some());
1784 assert!(consumer.allocate_message_queue_strategy().is_some());
1785
1786 let impl_config = &consumer
1787 .default_mqpush_consumer_impl
1788 .as_ref()
1789 .expect("push consumer impl should exist")
1790 .consumer_config;
1791
1792 assert_eq!(impl_config.consume_concurrently_max_span, 1234);
1793 assert_eq!(impl_config.consume_from_where, ConsumeFromWhere::ConsumeFromFirstOffset);
1794 assert_eq!(impl_config.consume_message_batch_max_size, 8);
1795 assert_eq!(impl_config.consumer_group.as_str(), "push_runtime_config_group_updated");
1796 assert_eq!(impl_config.consume_thread_max, 48);
1797 assert_eq!(impl_config.consume_thread_min, 12);
1798 assert_eq!(impl_config.message_model, MessageModel::Broadcasting);
1799 assert_eq!(impl_config.pull_batch_size, 64);
1800 assert_eq!(impl_config.pull_interval, 15);
1801 assert_eq!(impl_config.pull_threshold_for_queue, 2048);
1802 assert_eq!(impl_config.pop_threshold_for_queue, 128);
1803 assert_eq!(impl_config.pull_threshold_for_topic, 4096);
1804 assert_eq!(impl_config.pull_threshold_size_for_queue, 256);
1805 assert_eq!(impl_config.pull_threshold_size_for_topic, 512);
1806 assert_eq!(
1807 impl_config.consume_timestamp.as_ref().map(CheetahString::as_str),
1808 Some("20260610101010")
1809 );
1810 assert!(impl_config.post_subscription_when_pull);
1811 assert!(impl_config.unit_mode);
1812 assert_eq!(impl_config.adjust_thread_pool_nums_threshold, 222_222);
1813 assert_eq!(impl_config.max_reconsume_times, 19);
1814 assert_eq!(impl_config.suspend_current_queue_time_millis, 3333);
1815 assert_eq!(impl_config.consume_timeout, 44);
1816 assert_eq!(impl_config.pop_invisible_time, 55_555);
1817 assert_eq!(impl_config.await_termination_millis_when_shutdown, 66_666);
1818 assert_eq!(impl_config.pull_batch_size_in_bytes, 512 * 1024);
1819 assert_eq!(impl_config.pop_batch_nums, 16);
1820 assert!(!impl_config.client_rebalance);
1821 assert!(impl_config.message_queue_listener.is_some());
1822
1823 consumer.clear_consume_timestamp();
1824 assert!(consumer.consume_timestamp().is_none());
1825 }
1826
1827 #[tokio::test]
1828 async fn push_pause_state_facade_matches_impl_like_java() {
1829 let consumer = DefaultMQPushConsumer::builder()
1830 .consumer_group("push_pause_state_group")
1831 .build();
1832
1833 assert!(!consumer.is_pause());
1834 consumer.suspend().await;
1835 assert!(consumer.is_pause());
1836 consumer.resume().await;
1837 assert!(!consumer.is_pause());
1838 }
1839
1840 #[test]
1841 fn is_consume_orderly_facade_reflects_impl_state_like_java() {
1842 let mut consumer = DefaultMQPushConsumer::builder()
1843 .consumer_group("push_orderly_state_group")
1844 .build();
1845
1846 assert!(!consumer.is_consume_orderly());
1847
1848 consumer
1849 .default_mqpush_consumer_impl
1850 .as_mut()
1851 .expect("push consumer impl should exist")
1852 .set_consume_orderly(true);
1853
1854 assert!(consumer.is_consume_orderly());
1855 }
1856
1857 #[tokio::test]
1858 async fn push_facade_namespace_subscribe_wraps_topic_like_java() {
1859 let mut consumer = namespaced_push_consumer();
1860
1861 consumer
1862 .subscribe("TopicA", "TagA")
1863 .await
1864 .expect("subscribe should succeed before start");
1865
1866 let subscriptions = consumer
1867 .default_mqpush_consumer_impl
1868 .as_ref()
1869 .expect("push consumer impl should exist")
1870 .subscriptions();
1871 let subscription = subscriptions
1872 .iter()
1873 .find(|subscription| subscription.topic.as_str() == "ns%TopicA")
1874 .expect("namespaced topic should be subscribed");
1875 assert_eq!(subscription.sub_string.as_str(), "TagA");
1876 assert!(!subscriptions
1877 .iter()
1878 .any(|subscription| subscription.topic.as_str() == "TopicA"));
1879 }
1880
1881 #[tokio::test]
1882 async fn push_facade_namespace_selector_subscribe_wraps_topic_like_java() {
1883 let mut consumer = namespaced_push_consumer();
1884
1885 consumer
1886 .subscribe_with_selector("TopicB", Some(MessageSelector::by_tag("TagB")))
1887 .await
1888 .expect("selector subscribe should succeed before start");
1889
1890 let subscriptions = consumer
1891 .default_mqpush_consumer_impl
1892 .as_ref()
1893 .expect("push consumer impl should exist")
1894 .subscriptions();
1895 let subscription = subscriptions
1896 .iter()
1897 .find(|subscription| subscription.topic.as_str() == "ns%TopicB")
1898 .expect("namespaced selector topic should be subscribed");
1899 assert_eq!(subscription.sub_string.as_str(), "TagB");
1900 assert!(!subscriptions
1901 .iter()
1902 .any(|subscription| subscription.topic.as_str() == "TopicB"));
1903 }
1904
1905 #[tokio::test]
1906 async fn push_facade_namespace_unsubscribe_passes_topic_through_like_java() {
1907 let mut consumer = namespaced_push_consumer();
1908 consumer
1909 .subscribe("TopicC", "*")
1910 .await
1911 .expect("subscribe should succeed before start");
1912
1913 consumer.unsubscribe("TopicC").await;
1914
1915 let subscriptions = consumer
1916 .default_mqpush_consumer_impl
1917 .as_ref()
1918 .expect("push consumer impl should exist")
1919 .subscriptions();
1920 assert!(subscriptions
1921 .iter()
1922 .any(|subscription| subscription.topic.as_str() == "ns%TopicC"));
1923
1924 consumer.unsubscribe("ns%TopicC").await;
1925
1926 let subscriptions = consumer
1927 .default_mqpush_consumer_impl
1928 .as_ref()
1929 .expect("push consumer impl should exist")
1930 .subscriptions();
1931 assert!(!subscriptions
1932 .iter()
1933 .any(|subscription| subscription.topic.as_str() == "ns%TopicC"));
1934 }
1935
1936 #[tokio::test]
1937 async fn custom_trace_dispatcher_registers_hook_and_starts_with_client_config() {
1938 let dispatcher = Arc::new(CapturingTraceDispatcher::default());
1939 let trace_dispatcher: ArcTraceDispatcher = dispatcher.clone();
1940 let mut client_config = ClientConfig::default();
1941 client_config.set_namesrv_addr(CheetahString::from_static_str("127.0.0.1:9876"));
1942 client_config.set_access_channel(AccessChannel::Cloud);
1943
1944 let mut consumer = DefaultMQPushConsumer::builder()
1945 .consumer_group("push_trace_group")
1946 .client_config(client_config)
1947 .trace_dispatcher(Some(trace_dispatcher))
1948 .build();
1949
1950 let trace_dispatcher_to_start = {
1951 let consumer_impl = consumer
1952 .default_mqpush_consumer_impl
1953 .as_mut()
1954 .expect("push consumer impl should exist");
1955 DefaultMQPushConsumer::prepare_trace_dispatcher(
1956 &consumer.client_config,
1957 &mut consumer.consumer_config,
1958 consumer_impl,
1959 )
1960 .expect("custom dispatcher should be prepared")
1961 };
1962
1963 assert_eq!(
1964 consumer
1965 .default_mqpush_consumer_impl
1966 .as_ref()
1967 .expect("push consumer impl should exist")
1968 .consume_message_hook_count(),
1969 1
1970 );
1971
1972 consumer.start_trace_dispatcher(trace_dispatcher_to_start).await;
1973 assert_eq!(dispatcher.start_count.load(Ordering::SeqCst), 1);
1974 assert_eq!(
1975 dispatcher
1976 .last_name_srv_addr
1977 .lock()
1978 .expect("name server lock")
1979 .as_deref(),
1980 Some("127.0.0.1:9876")
1981 );
1982 assert_eq!(
1983 *dispatcher.last_access_channel.lock().expect("access channel lock"),
1984 Some(AccessChannel::Cloud)
1985 );
1986 }
1987}