1use std::collections::HashMap;
16use std::collections::HashSet;
17use std::sync::Arc;
18use std::sync::RwLock as StdRwLock;
19
20use cheetah_string::CheetahString;
21use rocketmq_common::common::consumer::consume_from_where::ConsumeFromWhere;
22use rocketmq_common::common::message::message_decoder;
23use rocketmq_common::common::message::message_ext::MessageExt;
24use rocketmq_common::common::message::message_queue::MessageQueue;
25use rocketmq_common::common::topic::TopicValidator;
26use rocketmq_error::RocketMQError;
27use rocketmq_error::RocketMQResult;
28use rocketmq_remoting::protocol::body::consumer_running_info::ConsumerRunningInfo;
29use rocketmq_remoting::protocol::heartbeat::message_model::MessageModel;
30use rocketmq_remoting::protocol::heartbeat::subscription_data::SubscriptionData;
31use rocketmq_remoting::protocol::namespace_util::NamespaceUtil;
32use rocketmq_remoting::runtime::RPCHook;
33use rocketmq_rust::ArcMut;
34use tokio::sync::OnceCell;
35use tokio::sync::RwLock;
36
37use crate::base::client_config::ClientConfig;
38use crate::base::query_result::QueryResult;
39use crate::consumer::allocate_message_queue_strategy::AllocateMessageQueueStrategy;
40use crate::consumer::consumer_impl::default_lite_pull_consumer_impl::validate_lite_pull_consume_from_where;
41use crate::consumer::consumer_impl::default_lite_pull_consumer_impl::DefaultLitePullConsumerImpl;
42use crate::consumer::consumer_impl::default_lite_pull_consumer_impl::LitePullConsumerConfig;
43use crate::consumer::default_lite_pull_consumer_builder::DefaultLitePullConsumerBuilder;
44use crate::consumer::default_lite_pull_consumer_builder::MIN_AUTOCOMMIT_INTERVAL_MILLIS;
45use crate::consumer::lite_pull_consumer::LitePullConsumer;
46use crate::consumer::message_queue_listener::ArcMessageQueueListener;
47use crate::consumer::message_queue_listener::MessageQueueListener;
48use crate::consumer::message_selector::MessageSelector;
49use crate::consumer::mq_consumer::MQConsumer;
50use crate::consumer::mq_consumer_inner::MQConsumerInner;
51use crate::consumer::store::offset_store::OffsetStore;
52use crate::consumer::topic_message_queue_change_listener::TopicMessageQueueChangeListener;
53use crate::trace::async_trace_dispatcher::AsyncTraceDispatcher;
54use crate::trace::hook::consume_message_trace_hook_impl::ConsumeMessageTraceHookImpl;
55use crate::trace::trace_dispatcher::TraceDispatcher;
56use crate::trace::trace_dispatcher::Type;
57
58#[derive(Clone)]
145pub struct DefaultLitePullConsumer {
146 client_config: ArcMut<ClientConfig>,
148
149 consumer_config: ArcMut<LitePullConsumerConfig>,
151
152 default_lite_pull_consumer_impl: Arc<OnceCell<ArcMut<DefaultLitePullConsumerImpl>>>,
154
155 rpc_hook: Option<Arc<dyn RPCHook>>,
157
158 trace_dispatcher: Arc<RwLock<Option<Arc<dyn TraceDispatcher + Send + Sync>>>>,
160
161 enable_msg_trace: bool,
163
164 custom_trace_topic: Option<CheetahString>,
166
167 message_queue_listener: Arc<StdRwLock<Option<ArcMessageQueueListener>>>,
169
170 offset_store: Arc<StdRwLock<Option<ArcMut<OffsetStore>>>>,
172}
173
174impl DefaultLitePullConsumer {
175 pub fn new(
179 client_config: ArcMut<ClientConfig>,
180 consumer_config: ArcMut<LitePullConsumerConfig>,
181 rpc_hook: Option<Arc<dyn RPCHook>>,
182 trace_dispatcher: Option<Arc<dyn TraceDispatcher + Send + Sync>>,
183 enable_msg_trace: bool,
184 custom_trace_topic: Option<CheetahString>,
185 ) -> Self {
186 Self {
187 client_config,
188 consumer_config,
189 default_lite_pull_consumer_impl: Arc::new(OnceCell::new()),
190 rpc_hook,
191 trace_dispatcher: Arc::new(RwLock::new(trace_dispatcher)),
192 enable_msg_trace,
193 custom_trace_topic,
194 message_queue_listener: Arc::new(StdRwLock::new(None)),
195 offset_store: Arc::new(StdRwLock::new(None)),
196 }
197 }
198
199 pub fn builder() -> DefaultLitePullConsumerBuilder {
211 DefaultLitePullConsumerBuilder::new()
212 }
213
214 pub async fn start(&self) -> RocketMQResult<()> {
216 <Self as LitePullConsumer>::start(self).await
217 }
218
219 pub async fn shutdown(&self) {
221 <Self as LitePullConsumer>::shutdown(self).await;
222 }
223
224 pub async fn is_running(&self) -> bool {
226 <Self as LitePullConsumer>::is_running(self).await
227 }
228
229 pub async fn consumer_running_info(&self) -> RocketMQResult<ConsumerRunningInfo> {
231 let impl_ = self.try_impl_()?;
232 Ok(MQConsumerInner::consumer_running_info(impl_.as_ref()).await)
233 }
234
235 pub async fn subscribe(&self, topic: &str) -> RocketMQResult<()> {
237 <Self as LitePullConsumer>::subscribe(self, topic).await
238 }
239
240 pub async fn subscribe_with_expression(&self, topic: &str, sub_expression: &str) -> RocketMQResult<()> {
242 <Self as LitePullConsumer>::subscribe_with_expression(self, topic, sub_expression).await
243 }
244
245 pub async fn subscribe_with_listener<MQL>(
247 &self,
248 topic: &str,
249 sub_expression: &str,
250 listener: MQL,
251 ) -> RocketMQResult<()>
252 where
253 MQL: MessageQueueListener + 'static,
254 {
255 <Self as LitePullConsumer>::subscribe_with_listener(self, topic, sub_expression, listener).await
256 }
257
258 pub async fn subscribe_with_selector(&self, topic: &str, selector: Option<MessageSelector>) -> RocketMQResult<()> {
260 <Self as LitePullConsumer>::subscribe_with_selector(self, topic, selector).await
261 }
262
263 pub async fn unsubscribe(&self, topic: &str) {
265 <Self as LitePullConsumer>::unsubscribe(self, topic).await;
266 }
267
268 pub async fn assignment(&self) -> RocketMQResult<HashSet<MessageQueue>> {
270 <Self as LitePullConsumer>::assignment(self).await
271 }
272
273 pub async fn assign(&self, message_queues: Vec<MessageQueue>) -> RocketMQResult<()> {
275 <Self as LitePullConsumer>::assign(self, message_queues).await
276 }
277
278 pub async fn set_sub_expression_for_assign(&self, topic: &str, sub_expression: &str) -> RocketMQResult<()> {
280 <Self as LitePullConsumer>::set_sub_expression_for_assign(self, topic, sub_expression).await
281 }
282
283 pub async fn build_subscriptions_for_heartbeat(
285 &self,
286 sub_expression_map: &mut HashMap<String, MessageSelector>,
287 ) -> RocketMQResult<()> {
288 <Self as LitePullConsumer>::build_subscriptions_for_heartbeat(self, sub_expression_map).await
289 }
290
291 pub async fn subscriptions_for_heartbeat(&self) -> HashSet<SubscriptionData> {
293 <Self as LitePullConsumer>::subscriptions_for_heartbeat(self).await
294 }
295
296 pub async fn get_subscriptions_for_heartbeat(&self) -> HashSet<SubscriptionData> {
298 self.subscriptions_for_heartbeat().await
299 }
300
301 pub async fn poll_zero_copy(&self) -> Vec<ArcMut<MessageExt>> {
303 <Self as LitePullConsumer>::poll_zero_copy(self).await
304 }
305
306 pub async fn poll_with_timeout_zero_copy(&self, timeout: u64) -> Vec<ArcMut<MessageExt>> {
308 <Self as LitePullConsumer>::poll_with_timeout_zero_copy(self, timeout).await
309 }
310
311 pub async fn poll(&self) -> Vec<MessageExt> {
313 <Self as LitePullConsumer>::poll(self).await
314 }
315
316 pub async fn poll_with_timeout(&self, timeout: u64) -> Vec<MessageExt> {
318 <Self as LitePullConsumer>::poll_with_timeout(self, timeout).await
319 }
320
321 pub async fn message_model(&self) -> MessageModel {
323 <Self as LitePullConsumer>::message_model(self).await
324 }
325
326 pub async fn get_message_model(&self) -> MessageModel {
328 self.message_model().await
329 }
330
331 pub async fn set_message_model(&self, message_model: MessageModel) {
333 <Self as LitePullConsumer>::set_message_model(self, message_model).await;
334 }
335
336 pub async fn consume_from_where(&self) -> ConsumeFromWhere {
338 <Self as LitePullConsumer>::consume_from_where(self).await
339 }
340
341 pub async fn get_consume_from_where(&self) -> ConsumeFromWhere {
343 self.consume_from_where().await
344 }
345
346 pub async fn set_consume_from_where(&self, consume_from_where: ConsumeFromWhere) -> RocketMQResult<()> {
348 <Self as LitePullConsumer>::set_consume_from_where(self, consume_from_where).await
349 }
350
351 pub async fn consume_timestamp(&self) -> Option<CheetahString> {
353 <Self as LitePullConsumer>::consume_timestamp(self).await
354 }
355
356 pub async fn get_consume_timestamp(&self) -> Option<CheetahString> {
358 self.consume_timestamp().await
359 }
360
361 pub async fn set_consume_timestamp(&self, consume_timestamp: Option<CheetahString>) {
363 <Self as LitePullConsumer>::set_consume_timestamp(self, consume_timestamp).await;
364 }
365
366 pub async fn allocate_message_queue_strategy(&self) -> Arc<dyn AllocateMessageQueueStrategy + Send + Sync> {
368 <Self as LitePullConsumer>::allocate_message_queue_strategy(self).await
369 }
370
371 pub async fn get_allocate_message_queue_strategy(&self) -> Arc<dyn AllocateMessageQueueStrategy + Send + Sync> {
373 self.allocate_message_queue_strategy().await
374 }
375
376 pub async fn set_allocate_message_queue_strategy(
378 &self,
379 allocate_message_queue_strategy: Arc<dyn AllocateMessageQueueStrategy + Send + Sync>,
380 ) {
381 <Self as LitePullConsumer>::set_allocate_message_queue_strategy(self, allocate_message_queue_strategy).await;
382 }
383
384 pub async fn message_queue_listener(&self) -> Option<ArcMessageQueueListener> {
386 <Self as LitePullConsumer>::message_queue_listener(self).await
387 }
388
389 pub async fn get_message_queue_listener(&self) -> Option<ArcMessageQueueListener> {
391 self.message_queue_listener().await
392 }
393
394 pub async fn set_message_queue_listener(&self, message_queue_listener: Option<ArcMessageQueueListener>) {
396 <Self as LitePullConsumer>::set_message_queue_listener(self, message_queue_listener).await;
397 }
398
399 pub async fn offset_store(&self) -> Option<ArcMut<OffsetStore>> {
401 <Self as LitePullConsumer>::offset_store(self).await
402 }
403
404 pub async fn get_offset_store(&self) -> Option<ArcMut<OffsetStore>> {
406 self.offset_store().await
407 }
408
409 pub async fn set_offset_store(&self, offset_store: Option<ArcMut<OffsetStore>>) -> RocketMQResult<()> {
411 <Self as LitePullConsumer>::set_offset_store(self, offset_store).await
412 }
413
414 pub async fn topic_metadata_check_interval_millis(&self) -> u64 {
416 <Self as LitePullConsumer>::topic_metadata_check_interval_millis(self).await
417 }
418
419 pub async fn get_topic_metadata_check_interval_millis(&self) -> u64 {
421 self.topic_metadata_check_interval_millis().await
422 }
423
424 pub async fn set_topic_metadata_check_interval_millis(&self, interval_millis: u64) {
426 <Self as LitePullConsumer>::set_topic_metadata_check_interval_millis(self, interval_millis).await;
427 }
428
429 pub async fn poll_timeout_millis(&self) -> u64 {
431 <Self as LitePullConsumer>::poll_timeout_millis(self).await
432 }
433
434 pub async fn get_poll_timeout_millis(&self) -> u64 {
436 self.poll_timeout_millis().await
437 }
438
439 pub async fn set_poll_timeout_millis(&self, timeout_millis: u64) {
441 <Self as LitePullConsumer>::set_poll_timeout_millis(self, timeout_millis).await;
442 }
443
444 pub async fn broker_suspend_max_time_millis(&self) -> u64 {
446 <Self as LitePullConsumer>::broker_suspend_max_time_millis(self).await
447 }
448
449 pub async fn get_broker_suspend_max_time_millis(&self) -> u64 {
451 self.broker_suspend_max_time_millis().await
452 }
453
454 pub async fn set_broker_suspend_max_time_millis(&self, timeout_millis: u64) {
456 <Self as LitePullConsumer>::set_broker_suspend_max_time_millis(self, timeout_millis).await;
457 }
458
459 pub async fn consumer_timeout_millis_when_suspend(&self) -> u64 {
461 <Self as LitePullConsumer>::consumer_timeout_millis_when_suspend(self).await
462 }
463
464 pub async fn get_consumer_timeout_millis_when_suspend(&self) -> u64 {
466 self.consumer_timeout_millis_when_suspend().await
467 }
468
469 pub async fn set_consumer_timeout_millis_when_suspend(&self, timeout_millis: u64) {
471 <Self as LitePullConsumer>::set_consumer_timeout_millis_when_suspend(self, timeout_millis).await;
472 }
473
474 pub async fn consumer_pull_timeout_millis(&self) -> u64 {
476 <Self as LitePullConsumer>::consumer_pull_timeout_millis(self).await
477 }
478
479 pub async fn get_consumer_pull_timeout_millis(&self) -> u64 {
481 self.consumer_pull_timeout_millis().await
482 }
483
484 pub async fn set_consumer_pull_timeout_millis(&self, timeout_millis: u64) {
486 <Self as LitePullConsumer>::set_consumer_pull_timeout_millis(self, timeout_millis).await;
487 }
488
489 pub async fn pull_batch_size(&self) -> i32 {
491 <Self as LitePullConsumer>::pull_batch_size(self).await
492 }
493
494 pub async fn get_pull_batch_size(&self) -> i32 {
496 self.pull_batch_size().await
497 }
498
499 pub async fn set_pull_batch_size(&self, pull_batch_size: i32) {
501 <Self as LitePullConsumer>::set_pull_batch_size(self, pull_batch_size).await;
502 }
503
504 pub async fn pull_thread_nums(&self) -> usize {
506 <Self as LitePullConsumer>::pull_thread_nums(self).await
507 }
508
509 pub async fn get_pull_thread_nums(&self) -> usize {
511 self.pull_thread_nums().await
512 }
513
514 pub async fn set_pull_thread_nums(&self, pull_thread_nums: usize) {
516 <Self as LitePullConsumer>::set_pull_thread_nums(self, pull_thread_nums).await;
517 }
518
519 pub async fn pull_threshold_for_all(&self) -> i64 {
521 <Self as LitePullConsumer>::pull_threshold_for_all(self).await
522 }
523
524 pub async fn get_pull_threshold_for_all(&self) -> i64 {
526 self.pull_threshold_for_all().await
527 }
528
529 pub async fn set_pull_threshold_for_all(&self, pull_threshold_for_all: i64) {
531 <Self as LitePullConsumer>::set_pull_threshold_for_all(self, pull_threshold_for_all).await;
532 }
533
534 pub async fn pull_threshold_for_queue(&self) -> i64 {
536 <Self as LitePullConsumer>::pull_threshold_for_queue(self).await
537 }
538
539 pub async fn get_pull_threshold_for_queue(&self) -> i64 {
541 self.pull_threshold_for_queue().await
542 }
543
544 pub async fn set_pull_threshold_for_queue(&self, pull_threshold_for_queue: i64) {
546 <Self as LitePullConsumer>::set_pull_threshold_for_queue(self, pull_threshold_for_queue).await;
547 }
548
549 pub async fn pull_threshold_size_for_queue(&self) -> i32 {
551 <Self as LitePullConsumer>::pull_threshold_size_for_queue(self).await
552 }
553
554 pub async fn get_pull_threshold_size_for_queue(&self) -> i32 {
556 self.pull_threshold_size_for_queue().await
557 }
558
559 pub async fn set_pull_threshold_size_for_queue(&self, pull_threshold_size_for_queue: i32) {
561 <Self as LitePullConsumer>::set_pull_threshold_size_for_queue(self, pull_threshold_size_for_queue).await;
562 }
563
564 pub async fn consume_max_span(&self) -> i64 {
566 <Self as LitePullConsumer>::consume_max_span(self).await
567 }
568
569 pub async fn get_consume_max_span(&self) -> i64 {
571 self.consume_max_span().await
572 }
573
574 pub async fn set_consume_max_span(&self, consume_max_span: i64) {
576 <Self as LitePullConsumer>::set_consume_max_span(self, consume_max_span).await;
577 }
578
579 pub async fn is_connect_broker_by_user(&self) -> bool {
581 <Self as LitePullConsumer>::is_connect_broker_by_user(self).await
582 }
583
584 pub async fn set_connect_broker_by_user(&self, connect_broker_by_user: bool) {
586 <Self as LitePullConsumer>::set_connect_broker_by_user(self, connect_broker_by_user).await;
587 }
588
589 pub async fn default_broker_id(&self) -> u64 {
591 <Self as LitePullConsumer>::default_broker_id(self).await
592 }
593
594 pub async fn get_default_broker_id(&self) -> u64 {
596 self.default_broker_id().await
597 }
598
599 pub async fn set_default_broker_id(&self, broker_id: u64) {
601 <Self as LitePullConsumer>::set_default_broker_id(self, broker_id).await;
602 }
603
604 pub async fn fetch_message_queues(&self, topic: &str) -> RocketMQResult<Vec<MessageQueue>> {
606 <Self as LitePullConsumer>::fetch_message_queues(self, topic).await
607 }
608
609 pub async fn committed(&self, message_queue: &MessageQueue) -> RocketMQResult<i64> {
611 <Self as LitePullConsumer>::committed(self, message_queue).await
612 }
613
614 pub async fn commit_all(&self) -> RocketMQResult<()> {
616 <Self as LitePullConsumer>::commit_all(self).await
617 }
618
619 pub async fn commit_with_map(&self, offset_map: HashMap<MessageQueue, i64>, persist: bool) {
621 <Self as LitePullConsumer>::commit_with_map(self, offset_map, persist).await;
622 }
623
624 pub async fn commit(&self) {
626 <Self as LitePullConsumer>::commit(self).await;
627 }
628
629 pub async fn commit_with_set(&self, message_queues: HashSet<MessageQueue>, persist: bool) {
631 <Self as LitePullConsumer>::commit_with_set(self, message_queues, persist).await;
632 }
633
634 pub async fn commit_sync(&self) {
636 <Self as LitePullConsumer>::commit_sync(self).await;
637 }
638
639 pub async fn commit_sync_with_map(&self, offset_map: HashMap<MessageQueue, i64>, persist: bool) {
641 <Self as LitePullConsumer>::commit_sync_with_map(self, offset_map, persist).await;
642 }
643
644 pub async fn is_auto_commit(&self) -> bool {
646 <Self as LitePullConsumer>::is_auto_commit(self).await
647 }
648
649 pub async fn set_auto_commit(&self, auto_commit: bool) {
651 <Self as LitePullConsumer>::set_auto_commit(self, auto_commit).await;
652 }
653
654 pub async fn is_unit_mode(&self) -> bool {
656 <Self as LitePullConsumer>::is_unit_mode(self).await
657 }
658
659 pub async fn set_unit_mode(&self, unit_mode: bool) {
661 <Self as LitePullConsumer>::set_unit_mode(self, unit_mode).await;
662 }
663
664 pub async fn auto_commit_interval_millis(&self) -> u64 {
666 <Self as LitePullConsumer>::auto_commit_interval_millis(self).await
667 }
668
669 pub async fn get_auto_commit_interval_millis(&self) -> u64 {
671 self.auto_commit_interval_millis().await
672 }
673
674 pub async fn set_auto_commit_interval_millis(&self, interval_millis: u64) {
676 <Self as LitePullConsumer>::set_auto_commit_interval_millis(self, interval_millis).await;
677 }
678
679 pub async fn offset_for_timestamp(&self, message_queue: &MessageQueue, timestamp: u64) -> RocketMQResult<i64> {
681 <Self as LitePullConsumer>::offset_for_timestamp(self, message_queue, timestamp).await
682 }
683
684 pub async fn earliest_msg_store_time(&self, message_queue: &MessageQueue) -> RocketMQResult<i64> {
686 <Self as LitePullConsumer>::earliest_msg_store_time(self, message_queue).await
687 }
688
689 pub async fn max_offset(&self, message_queue: &MessageQueue) -> RocketMQResult<i64> {
691 <Self as LitePullConsumer>::max_offset(self, message_queue).await
692 }
693
694 pub async fn min_offset(&self, message_queue: &MessageQueue) -> RocketMQResult<i64> {
696 <Self as LitePullConsumer>::min_offset(self, message_queue).await
697 }
698
699 pub async fn create_topic(
701 &self,
702 key: &str,
703 new_topic: &str,
704 queue_num: i32,
705 attributes: HashMap<String, String>,
706 ) -> RocketMQResult<()> {
707 self.create_topic_with_flag(key, new_topic, queue_num, 0, attributes)
708 .await
709 }
710
711 pub async fn create_topic_with_flag(
713 &self,
714 key: &str,
715 new_topic: &str,
716 queue_num: i32,
717 topic_sys_flag: i32,
718 attributes: HashMap<String, String>,
719 ) -> RocketMQResult<()> {
720 let new_topic = self.with_namespace(new_topic);
721 self.try_impl_()?
722 .create_topic(key, new_topic.as_str(), queue_num, topic_sys_flag, attributes)
723 .await
724 }
725
726 pub async fn query_message(
728 &self,
729 topic: &str,
730 key: &str,
731 max_num: i32,
732 begin: u64,
733 end: u64,
734 ) -> RocketMQResult<QueryResult> {
735 let topic = self.with_namespace(topic);
736 self.try_impl_()?
737 .query_message(topic.as_str(), key, max_num, begin, end)
738 .await
739 }
740
741 pub async fn view_message(&self, topic: &str, msg_id: &str) -> RocketMQResult<MessageExt> {
743 let topic = self.with_namespace(topic);
744 let impl_ = self.try_impl_()?;
745 if message_decoder::decode_message_id(msg_id).is_ok() {
746 impl_.view_message(topic.as_str(), msg_id).await
747 } else {
748 impl_.query_message_by_uniq_key(topic.as_str(), msg_id).await
749 }
750 }
751
752 pub async fn pause(&self, message_queues: Vec<MessageQueue>) {
754 <Self as LitePullConsumer>::pause(self, message_queues).await;
755 }
756
757 pub async fn resume(&self, message_queues: Vec<MessageQueue>) {
759 <Self as LitePullConsumer>::resume(self, message_queues).await;
760 }
761
762 pub async fn is_paused(&self, message_queue: &MessageQueue) -> bool {
764 <Self as LitePullConsumer>::is_paused(self, message_queue).await
765 }
766
767 pub async fn seek(&self, message_queue: &MessageQueue, offset: i64) -> RocketMQResult<()> {
769 <Self as LitePullConsumer>::seek(self, message_queue, offset).await
770 }
771
772 pub async fn seek_to_begin(&self, message_queue: &MessageQueue) -> RocketMQResult<()> {
774 <Self as LitePullConsumer>::seek_to_begin(self, message_queue).await
775 }
776
777 pub async fn seek_to_end(&self, message_queue: &MessageQueue) -> RocketMQResult<()> {
779 <Self as LitePullConsumer>::seek_to_end(self, message_queue).await
780 }
781
782 pub async fn update_name_server_address(&self, name_server_address: &str) {
784 <Self as LitePullConsumer>::update_name_server_address(self, name_server_address).await;
785 }
786
787 pub async fn register_topic_message_queue_change_listener<TL>(
789 &self,
790 topic: &str,
791 listener: TL,
792 ) -> RocketMQResult<()>
793 where
794 TL: TopicMessageQueueChangeListener + 'static,
795 {
796 <Self as LitePullConsumer>::register_topic_message_queue_change_listener(self, topic, listener).await
797 }
798
799 pub fn consumer_group(&self) -> &CheetahString {
801 &self.consumer_config.consumer_group
802 }
803
804 pub fn get_consumer_group(&self) -> &CheetahString {
806 self.consumer_group()
807 }
808
809 pub fn set_consumer_group(&self, consumer_group: impl Into<CheetahString>) -> RocketMQResult<()> {
816 let consumer_group = consumer_group.into();
817 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
818 impl_.set_consumer_group(consumer_group)?;
819 } else {
820 self.consumer_config.mut_from_ref().consumer_group = consumer_group;
821 }
822 Ok(())
823 }
824
825 pub fn namespace(&self) -> Option<CheetahString> {
827 self.client_config.mut_from_ref().get_namespace()
828 }
829
830 pub fn customized_trace_topic(&self) -> Option<CheetahString> {
832 self.custom_trace_topic.clone()
833 }
834
835 pub fn get_customized_trace_topic(&self) -> Option<CheetahString> {
837 self.customized_trace_topic()
838 }
839
840 pub fn set_customized_trace_topic(&mut self, customized_trace_topic: impl Into<CheetahString>) {
842 self.custom_trace_topic = Some(customized_trace_topic.into());
843 }
844
845 pub fn clear_customized_trace_topic(&mut self) {
847 self.custom_trace_topic = None;
848 }
849
850 pub fn is_enable_msg_trace(&self) -> bool {
852 self.enable_msg_trace
853 }
854
855 pub fn set_enable_msg_trace(&mut self, enable_msg_trace: bool) {
857 self.enable_msg_trace = enable_msg_trace;
858 }
859
860 pub fn is_use_tls(&self) -> bool {
862 self.client_config.is_use_tls()
863 }
864
865 pub async fn set_use_tls(&self, use_tls: bool) {
867 self.client_config.mut_from_ref().set_use_tls(use_tls);
868 if let Some(dispatcher) = self.trace_dispatcher.read().await.as_ref().cloned() {
869 if let Some(async_dispatcher) = dispatcher.as_any().downcast_ref::<AsyncTraceDispatcher>() {
870 async_dispatcher.set_use_tls(use_tls);
871 }
872 }
873 }
874
875 pub async fn trace_dispatcher(&self) -> Option<Arc<dyn TraceDispatcher + Send + Sync>> {
877 self.trace_dispatcher.read().await.as_ref().cloned()
878 }
879
880 pub async fn get_trace_dispatcher(&self) -> Option<Arc<dyn TraceDispatcher + Send + Sync>> {
882 self.trace_dispatcher().await
883 }
884
885 pub fn client_config(&self) -> &ArcMut<ClientConfig> {
887 &self.client_config
888 }
889
890 pub fn consumer_config(&self) -> &ArcMut<LitePullConsumerConfig> {
892 &self.consumer_config
893 }
894
895 fn with_namespace(&self, resource: &str) -> CheetahString {
897 self.client_config
898 .mut_from_ref()
899 .with_namespace(CheetahString::from(resource))
900 }
901
902 fn without_namespace(&self, resource: &str) -> CheetahString {
904 match self.client_config.mut_from_ref().get_namespace() {
905 Some(namespace) if !namespace.is_empty() => {
906 NamespaceUtil::without_namespace_with_namespace(resource, namespace.as_str()).into()
907 }
908 _ => NamespaceUtil::without_namespace(resource).into(),
909 }
910 }
911
912 fn consumer_group_with_namespace(&self) -> CheetahString {
914 self.client_config
915 .mut_from_ref()
916 .with_namespace(self.consumer_config.consumer_group.clone())
917 }
918
919 fn queue_with_namespace(&self, mq: &MessageQueue) -> MessageQueue {
921 self.client_config.mut_from_ref().queue_with_namespace(mq.clone())
922 }
923
924 fn queue_without_namespace(&self, mq: &MessageQueue) -> MessageQueue {
926 match self.client_config.mut_from_ref().get_namespace() {
927 Some(namespace) if !namespace.is_empty() => {
928 let unwrapped_topic = NamespaceUtil::without_namespace_with_namespace(mq.topic(), namespace.as_str());
929 MessageQueue::from_parts(unwrapped_topic, mq.broker_name().clone(), mq.queue_id())
930 }
931 Some(_) | None => mq.clone(),
932 }
933 }
934
935 async fn init_trace_dispatcher_internal(&self, impl_: &ArcMut<DefaultLitePullConsumerImpl>) -> RocketMQResult<()> {
937 if !self.enable_msg_trace {
938 return Ok(());
939 }
940
941 let dispatcher_arc = {
942 let mut dispatcher_guard = self.trace_dispatcher.write().await;
943 if let Some(dispatcher) = dispatcher_guard.as_ref() {
944 dispatcher.clone()
945 } else {
946 let trace_topic = self
947 .custom_trace_topic
948 .as_ref()
949 .map(|t| t.as_str())
950 .unwrap_or(TopicValidator::RMQ_SYS_TRACE_TOPIC);
951
952 let dispatcher = AsyncTraceDispatcher::new(
953 self.consumer_config.consumer_group.as_str(),
954 Type::Consume,
955 self.client_config.trace_msg_batch_num,
956 trace_topic,
957 self.rpc_hook.clone(),
958 );
959 dispatcher.set_namespace_v2(self.client_config.namespace_v2.clone());
960 dispatcher.set_use_tls(self.client_config.use_tls);
961
962 let dispatcher_arc: Arc<dyn TraceDispatcher + Send + Sync> = Arc::new(dispatcher);
963 *dispatcher_guard = Some(dispatcher_arc.clone());
964 dispatcher_arc
965 }
966 };
967
968 let hook = Arc::new(ConsumeMessageTraceHookImpl::new(dispatcher_arc));
969 impl_.mut_from_ref().register_consume_message_hook(hook);
970
971 Ok(())
972 }
973
974 async fn start_trace_dispatcher(&self) {
976 if !self.enable_msg_trace {
977 return;
978 }
979
980 let dispatcher = self.trace_dispatcher.read().await.as_ref().cloned();
981 let Some(dispatcher) = dispatcher else {
982 return;
983 };
984
985 let name_server_addr = self
986 .client_config
987 .namesrv_addr
988 .as_ref()
989 .map(|addr| addr.as_str())
990 .unwrap_or_default();
991 if let Err(error) = dispatcher.start(name_server_addr, self.client_config.access_channel) {
992 tracing::warn!("trace dispatcher start failed: {}", error);
993 }
994 }
995
996 fn try_impl_(&self) -> RocketMQResult<&ArcMut<DefaultLitePullConsumerImpl>> {
998 self.default_lite_pull_consumer_impl
999 .get()
1000 .ok_or_else(|| RocketMQError::not_initialized("DefaultLitePullConsumer not started. Call start() first."))
1001 }
1002
1003 async fn get_or_init_impl(&self) -> RocketMQResult<&ArcMut<DefaultLitePullConsumerImpl>> {
1010 self.default_lite_pull_consumer_impl
1011 .get_or_try_init(|| async {
1012 let mut impl_ = ArcMut::new(DefaultLitePullConsumerImpl::new(
1013 self.client_config.clone(),
1014 self.consumer_config.clone(),
1015 ));
1016 let wrapper = impl_.clone();
1017 impl_.set_default_lite_pull_consumer_impl(wrapper);
1018 impl_.set_rpc_hook(self.rpc_hook.clone());
1019 impl_.set_message_queue_listener(self.current_message_queue_listener());
1020
1021 self.init_trace_dispatcher_internal(&impl_).await?;
1022
1023 impl_.set_consumer_group(self.consumer_group_with_namespace())?;
1024 if let Some(offset_store) = self.current_offset_store() {
1025 impl_.mut_from_ref().set_offset_store(Some(offset_store))?;
1026 }
1027
1028 Ok::<ArcMut<DefaultLitePullConsumerImpl>, rocketmq_error::RocketMQError>(impl_)
1029 })
1030 .await
1031 }
1032
1033 fn current_message_queue_listener(&self) -> Option<ArcMessageQueueListener> {
1034 self.message_queue_listener
1035 .read()
1036 .ok()
1037 .and_then(|listener| listener.clone())
1038 }
1039
1040 fn set_message_queue_listener_local(&self, listener: Option<ArcMessageQueueListener>) {
1041 match self.message_queue_listener.write() {
1042 Ok(mut current) => *current = listener,
1043 Err(error) => tracing::warn!("LitePull message queue listener lock poisoned: {}", error),
1044 }
1045 }
1046
1047 fn current_offset_store(&self) -> Option<ArcMut<OffsetStore>> {
1048 self.offset_store.read().ok().and_then(|store| store.clone())
1049 }
1050
1051 fn set_offset_store_local(&self, offset_store: Option<ArcMut<OffsetStore>>) {
1052 match self.offset_store.write() {
1053 Ok(mut current) => *current = offset_store,
1054 Err(error) => tracing::warn!("LitePull offset store lock poisoned: {}", error),
1055 }
1056 }
1057}
1058
1059#[allow(unused)]
1060impl LitePullConsumer for DefaultLitePullConsumer {
1061 async fn start(&self) -> RocketMQResult<()> {
1062 let impl_ = self.get_or_init_impl().await?;
1063
1064 impl_.mut_from_ref().start().await?;
1065 self.set_offset_store_local(impl_.offset_store());
1066 self.start_trace_dispatcher().await;
1067 Ok(())
1068 }
1069
1070 async fn shutdown(&self) {
1071 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1072 let _ = impl_.mut_from_ref().shutdown().await;
1073 }
1074
1075 if let Some(dispatcher) = self.trace_dispatcher.write().await.take() {
1077 dispatcher.shutdown();
1078 }
1079 }
1080
1081 async fn is_running(&self) -> bool {
1082 match self.default_lite_pull_consumer_impl.get() {
1083 Some(impl_) => impl_.is_running().await,
1084 None => false,
1085 }
1086 }
1087
1088 async fn subscribe(&self, topic: &str) -> RocketMQResult<()> {
1089 self.subscribe_with_expression(topic, "*").await
1090 }
1091
1092 async fn subscribe_with_expression(&self, topic: &str, sub_expression: &str) -> RocketMQResult<()> {
1093 let wrapped_topic = self.with_namespace(topic);
1094 self.get_or_init_impl()
1095 .await?
1096 .mut_from_ref()
1097 .subscribe(wrapped_topic, sub_expression)
1098 .await
1099 }
1100
1101 async fn subscribe_with_listener<MQL>(&self, topic: &str, sub_expression: &str, listener: MQL) -> RocketMQResult<()>
1102 where
1103 MQL: MessageQueueListener + 'static,
1104 {
1105 let wrapped_topic = self.with_namespace(topic);
1106 let listener: ArcMessageQueueListener = Arc::new(listener);
1107 self.get_or_init_impl()
1108 .await?
1109 .mut_from_ref()
1110 .subscribe_with_listener_arc(wrapped_topic, sub_expression, listener.clone())
1111 .await?;
1112 self.set_message_queue_listener_local(Some(listener));
1113 Ok(())
1114 }
1115
1116 async fn subscribe_with_selector(&self, topic: &str, selector: Option<MessageSelector>) -> RocketMQResult<()> {
1117 let wrapped_topic = self.with_namespace(topic);
1118 self.get_or_init_impl()
1119 .await?
1120 .mut_from_ref()
1121 .subscribe_with_selector(wrapped_topic, selector)
1122 .await
1123 }
1124
1125 async fn unsubscribe(&self, topic: &str) {
1126 let wrapped_topic = self.with_namespace(topic);
1127 match self.try_impl_() {
1128 Ok(impl_) => {
1129 if let Err(e) = impl_.mut_from_ref().unsubscribe(wrapped_topic).await {
1130 tracing::warn!("Failed to unsubscribe from topic {}: {}", topic, e);
1131 }
1132 }
1133 Err(e) => tracing::warn!("Failed to unsubscribe from topic {}: {}", topic, e),
1134 }
1135 }
1136
1137 async fn assignment(&self) -> RocketMQResult<HashSet<MessageQueue>> {
1138 let assignment = self.try_impl_()?.assignment().await;
1139
1140 let mut result = HashSet::with_capacity(assignment.len());
1142 for mq in assignment {
1143 result.insert(self.queue_without_namespace(&mq));
1144 }
1145
1146 Ok(result)
1147 }
1148
1149 async fn assign(&self, message_queues: Vec<MessageQueue>) -> RocketMQResult<()> {
1150 let wrapped_queues: Vec<_> = message_queues.iter().map(|mq| self.queue_with_namespace(mq)).collect();
1152
1153 self.get_or_init_impl()
1154 .await?
1155 .mut_from_ref()
1156 .assign(wrapped_queues)
1157 .await
1158 }
1159
1160 async fn set_sub_expression_for_assign(&self, topic: &str, sub_expression: &str) -> RocketMQResult<()> {
1161 let wrapped_topic = self.with_namespace(topic);
1162 self.get_or_init_impl()
1163 .await?
1164 .set_sub_expression_for_assign(wrapped_topic, sub_expression)
1165 .await
1166 }
1167
1168 async fn build_subscriptions_for_heartbeat(
1169 &self,
1170 sub_expression_map: &mut HashMap<String, MessageSelector>,
1171 ) -> RocketMQResult<()> {
1172 self.try_impl_()?
1173 .build_subscriptions_for_heartbeat(sub_expression_map)
1174 .await
1175 }
1176
1177 async fn subscriptions_for_heartbeat(&self) -> HashSet<SubscriptionData> {
1178 self.default_lite_pull_consumer_impl
1179 .get()
1180 .map_or_else(HashSet::new, |impl_| impl_.subscriptions_for_heartbeat())
1181 }
1182
1183 async fn poll_zero_copy(&self) -> Vec<ArcMut<MessageExt>> {
1185 match self.try_impl_() {
1186 Ok(impl_) => match impl_.poll(self.consumer_config.poll_timeout_millis).await {
1187 Ok(messages) => messages,
1188 Err(e) => {
1189 tracing::error!("Poll failed: {}", e);
1190 Vec::new()
1191 }
1192 },
1193 Err(e) => {
1194 tracing::error!("Poll failed: {}", e);
1195 Vec::new()
1196 }
1197 }
1198 }
1199
1200 async fn poll_with_timeout_zero_copy(&self, timeout: u64) -> Vec<ArcMut<MessageExt>> {
1202 match self.try_impl_() {
1203 Ok(impl_) => match impl_.poll_with_timeout(timeout).await {
1204 Ok(messages) => messages,
1205 Err(e) => {
1206 tracing::error!("Poll failed: {}", e);
1207 Vec::new()
1208 }
1209 },
1210 Err(e) => {
1211 tracing::error!("Poll failed: {}", e);
1212 Vec::new()
1213 }
1214 }
1215 }
1216
1217 async fn poll(&self) -> Vec<MessageExt> {
1219 self.poll_zero_copy()
1220 .await
1221 .into_iter()
1222 .map(|arc_mut| (*arc_mut).clone())
1223 .collect()
1224 }
1225
1226 async fn poll_with_timeout(&self, timeout: u64) -> Vec<MessageExt> {
1228 self.poll_with_timeout_zero_copy(timeout)
1229 .await
1230 .into_iter()
1231 .map(|arc_mut| (*arc_mut).clone())
1232 .collect()
1233 }
1234
1235 async fn message_model(&self) -> MessageModel {
1236 self.consumer_config.message_model
1237 }
1238
1239 async fn set_message_model(&self, message_model: MessageModel) {
1240 self.consumer_config.mut_from_ref().message_model = message_model;
1241 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1242 impl_.set_message_model(message_model);
1243 }
1244 }
1245
1246 async fn consume_from_where(&self) -> ConsumeFromWhere {
1247 self.consumer_config.consume_from_where
1248 }
1249
1250 async fn set_consume_from_where(&self, consume_from_where: ConsumeFromWhere) -> RocketMQResult<()> {
1251 validate_lite_pull_consume_from_where(consume_from_where)?;
1252 self.consumer_config.mut_from_ref().consume_from_where = consume_from_where;
1253 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1254 impl_.set_consume_from_where(consume_from_where)?;
1255 }
1256 Ok(())
1257 }
1258
1259 async fn consume_timestamp(&self) -> Option<CheetahString> {
1260 self.consumer_config.consume_timestamp.clone()
1261 }
1262
1263 async fn set_consume_timestamp(&self, consume_timestamp: Option<CheetahString>) {
1264 self.consumer_config.mut_from_ref().consume_timestamp = consume_timestamp.clone();
1265 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1266 impl_.set_consume_timestamp(consume_timestamp);
1267 }
1268 }
1269
1270 async fn allocate_message_queue_strategy(&self) -> Arc<dyn AllocateMessageQueueStrategy + Send + Sync> {
1271 self.default_lite_pull_consumer_impl.get().map_or_else(
1272 || self.consumer_config.allocate_message_queue_strategy.clone(),
1273 |impl_| impl_.allocate_message_queue_strategy(),
1274 )
1275 }
1276
1277 async fn set_allocate_message_queue_strategy(
1278 &self,
1279 allocate_message_queue_strategy: Arc<dyn AllocateMessageQueueStrategy + Send + Sync>,
1280 ) {
1281 self.consumer_config.mut_from_ref().allocate_message_queue_strategy = allocate_message_queue_strategy.clone();
1282 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1283 impl_.set_allocate_message_queue_strategy(allocate_message_queue_strategy);
1284 }
1285 }
1286
1287 async fn message_queue_listener(&self) -> Option<ArcMessageQueueListener> {
1288 self.default_lite_pull_consumer_impl
1289 .get()
1290 .and_then(|impl_| impl_.message_queue_listener())
1291 .or_else(|| self.current_message_queue_listener())
1292 }
1293
1294 async fn set_message_queue_listener(&self, message_queue_listener: Option<ArcMessageQueueListener>) {
1295 self.set_message_queue_listener_local(message_queue_listener.clone());
1296 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1297 impl_.set_message_queue_listener(message_queue_listener);
1298 }
1299 }
1300
1301 async fn offset_store(&self) -> Option<ArcMut<OffsetStore>> {
1302 self.default_lite_pull_consumer_impl
1303 .get()
1304 .and_then(|impl_| impl_.offset_store())
1305 .or_else(|| self.current_offset_store())
1306 }
1307
1308 async fn set_offset_store(&self, offset_store: Option<ArcMut<OffsetStore>>) -> RocketMQResult<()> {
1309 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1310 impl_.mut_from_ref().set_offset_store(offset_store.clone())?;
1311 }
1312 self.set_offset_store_local(offset_store);
1313 Ok(())
1314 }
1315
1316 async fn topic_metadata_check_interval_millis(&self) -> u64 {
1317 self.consumer_config.topic_metadata_check_interval_millis
1318 }
1319
1320 async fn set_topic_metadata_check_interval_millis(&self, interval_millis: u64) {
1321 self.consumer_config.mut_from_ref().topic_metadata_check_interval_millis = interval_millis;
1322 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1323 impl_.set_topic_metadata_check_interval_millis(interval_millis);
1324 }
1325 }
1326
1327 async fn poll_timeout_millis(&self) -> u64 {
1328 self.consumer_config.poll_timeout_millis
1329 }
1330
1331 async fn set_poll_timeout_millis(&self, timeout_millis: u64) {
1332 self.consumer_config.mut_from_ref().poll_timeout_millis = timeout_millis;
1333 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1334 impl_.set_poll_timeout_millis(timeout_millis);
1335 }
1336 }
1337
1338 async fn broker_suspend_max_time_millis(&self) -> u64 {
1339 self.consumer_config.broker_suspend_max_time_millis
1340 }
1341
1342 async fn set_broker_suspend_max_time_millis(&self, timeout_millis: u64) {
1343 self.consumer_config.mut_from_ref().broker_suspend_max_time_millis = timeout_millis;
1344 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1345 impl_.set_broker_suspend_max_time_millis(timeout_millis);
1346 }
1347 }
1348
1349 async fn consumer_timeout_millis_when_suspend(&self) -> u64 {
1350 self.consumer_config.consumer_timeout_millis_when_suspend
1351 }
1352
1353 async fn set_consumer_timeout_millis_when_suspend(&self, timeout_millis: u64) {
1354 self.consumer_config.mut_from_ref().consumer_timeout_millis_when_suspend = timeout_millis;
1355 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1356 impl_.set_consumer_timeout_millis_when_suspend(timeout_millis);
1357 }
1358 }
1359
1360 async fn consumer_pull_timeout_millis(&self) -> u64 {
1361 self.consumer_config.consumer_pull_timeout_millis
1362 }
1363
1364 async fn set_consumer_pull_timeout_millis(&self, timeout_millis: u64) {
1365 self.consumer_config.mut_from_ref().consumer_pull_timeout_millis = timeout_millis;
1366 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1367 impl_.set_consumer_pull_timeout_millis(timeout_millis);
1368 }
1369 }
1370
1371 async fn pull_batch_size(&self) -> i32 {
1372 self.consumer_config.pull_batch_size
1373 }
1374
1375 async fn set_pull_batch_size(&self, pull_batch_size: i32) {
1376 self.consumer_config.mut_from_ref().pull_batch_size = pull_batch_size;
1377 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1378 impl_.set_pull_batch_size(pull_batch_size);
1379 }
1380 }
1381
1382 async fn pull_thread_nums(&self) -> usize {
1383 self.consumer_config.pull_thread_nums
1384 }
1385
1386 async fn set_pull_thread_nums(&self, pull_thread_nums: usize) {
1387 self.consumer_config.mut_from_ref().pull_thread_nums = pull_thread_nums;
1388 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1389 impl_.set_pull_thread_nums(pull_thread_nums);
1390 }
1391 }
1392
1393 async fn pull_threshold_for_all(&self) -> i64 {
1394 self.consumer_config.pull_threshold_for_all
1395 }
1396
1397 async fn set_pull_threshold_for_all(&self, pull_threshold_for_all: i64) {
1398 self.consumer_config.mut_from_ref().pull_threshold_for_all = pull_threshold_for_all;
1399 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1400 impl_.set_pull_threshold_for_all(pull_threshold_for_all);
1401 }
1402 }
1403
1404 async fn pull_threshold_for_queue(&self) -> i64 {
1405 self.consumer_config.pull_threshold_for_queue
1406 }
1407
1408 async fn set_pull_threshold_for_queue(&self, pull_threshold_for_queue: i64) {
1409 self.consumer_config.mut_from_ref().pull_threshold_for_queue = pull_threshold_for_queue;
1410 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1411 impl_.set_pull_threshold_for_queue(pull_threshold_for_queue);
1412 }
1413 }
1414
1415 async fn pull_threshold_size_for_queue(&self) -> i32 {
1416 self.consumer_config.pull_threshold_size_for_queue
1417 }
1418
1419 async fn set_pull_threshold_size_for_queue(&self, pull_threshold_size_for_queue: i32) {
1420 self.consumer_config.mut_from_ref().pull_threshold_size_for_queue = pull_threshold_size_for_queue;
1421 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1422 impl_.set_pull_threshold_size_for_queue(pull_threshold_size_for_queue);
1423 }
1424 }
1425
1426 async fn consume_max_span(&self) -> i64 {
1427 self.consumer_config.consume_max_span
1428 }
1429
1430 async fn set_consume_max_span(&self, consume_max_span: i64) {
1431 self.consumer_config.mut_from_ref().consume_max_span = consume_max_span;
1432 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1433 impl_.set_consume_max_span(consume_max_span);
1434 }
1435 }
1436
1437 async fn is_connect_broker_by_user(&self) -> bool {
1438 self.default_lite_pull_consumer_impl
1439 .get()
1440 .map_or(self.consumer_config.connect_broker_by_user, |impl_| {
1441 impl_.is_connect_broker_by_user()
1442 })
1443 }
1444
1445 async fn set_connect_broker_by_user(&self, connect_broker_by_user: bool) {
1446 self.consumer_config.mut_from_ref().connect_broker_by_user = connect_broker_by_user;
1447 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1448 impl_.set_connect_broker_by_user(connect_broker_by_user);
1449 }
1450 }
1451
1452 async fn default_broker_id(&self) -> u64 {
1453 self.default_lite_pull_consumer_impl
1454 .get()
1455 .map_or(self.consumer_config.default_broker_id, |impl_| {
1456 impl_.default_broker_id()
1457 })
1458 }
1459
1460 async fn set_default_broker_id(&self, broker_id: u64) {
1461 self.consumer_config.mut_from_ref().default_broker_id = broker_id;
1462 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1463 impl_.set_default_broker_id(broker_id);
1464 }
1465 }
1466
1467 async fn fetch_message_queues(&self, topic: &str) -> RocketMQResult<Vec<MessageQueue>> {
1468 let wrapped_topic = self.with_namespace(topic);
1469 let queues = self.try_impl_()?.fetch_message_queues(wrapped_topic).await?;
1470
1471 let result: Vec<_> = queues.into_iter().map(|mq| self.queue_without_namespace(&mq)).collect();
1473
1474 Ok(result)
1475 }
1476
1477 async fn committed(&self, message_queue: &MessageQueue) -> RocketMQResult<i64> {
1478 let wrapped_mq = self.queue_with_namespace(message_queue);
1479 self.try_impl_()?.committed(&wrapped_mq).await
1480 }
1481
1482 async fn commit_all(&self) -> RocketMQResult<()> {
1483 self.try_impl_()?.commit_all().await
1484 }
1485
1486 async fn commit_with_map(&self, offset_map: HashMap<MessageQueue, i64>, persist: bool) {
1487 let mut wrapped_offsets = HashMap::with_capacity(offset_map.len());
1489 for (mq, offset) in offset_map {
1490 wrapped_offsets.insert(self.queue_with_namespace(&mq), offset);
1491 }
1492
1493 match self.try_impl_() {
1494 Ok(impl_) => {
1495 if let Err(e) = impl_.commit(wrapped_offsets, persist).await {
1496 tracing::warn!("commit_with_map failed: {}", e);
1497 }
1498 }
1499 Err(e) => tracing::warn!("commit_with_map failed: {}", e),
1500 }
1501 }
1502
1503 async fn commit(&self) {
1504 if let Err(e) = self.commit_all().await {
1505 tracing::warn!("commit failed: {}", e);
1506 }
1507 }
1508
1509 async fn commit_with_set(&self, message_queues: HashSet<MessageQueue>, persist: bool) {
1510 let wrapped_queues: HashSet<_> = message_queues.iter().map(|mq| self.queue_with_namespace(mq)).collect();
1512 let impl_ = match self.try_impl_() {
1513 Ok(impl_) => impl_,
1514 Err(e) => {
1515 tracing::warn!("commit_with_set failed: {}", e);
1516 return;
1517 }
1518 };
1519
1520 if let Err(e) = impl_.commit_message_queues(&wrapped_queues, persist).await {
1521 tracing::warn!("commit_with_set failed: {}", e);
1522 }
1523 }
1524
1525 async fn commit_sync(&self) {
1526 if let Err(e) = self.commit_all().await {
1528 tracing::warn!("commit_sync failed: {}", e);
1529 }
1530 }
1531
1532 async fn commit_sync_with_map(&self, offset_map: HashMap<MessageQueue, i64>, persist: bool) {
1533 self.commit_with_map(offset_map, persist).await;
1535 }
1536
1537 async fn is_auto_commit(&self) -> bool {
1538 self.consumer_config.auto_commit
1539 }
1540
1541 async fn set_auto_commit(&self, auto_commit: bool) {
1542 self.consumer_config.mut_from_ref().auto_commit = auto_commit;
1543 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1544 impl_.set_auto_commit(auto_commit);
1545 }
1546 }
1547
1548 async fn is_unit_mode(&self) -> bool {
1549 self.consumer_config.unit_mode
1550 }
1551
1552 async fn set_unit_mode(&self, unit_mode: bool) {
1553 self.consumer_config.mut_from_ref().unit_mode = unit_mode;
1554 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1555 impl_.set_unit_mode(unit_mode);
1556 }
1557 }
1558
1559 async fn auto_commit_interval_millis(&self) -> u64 {
1560 self.consumer_config.auto_commit_interval_millis
1561 }
1562
1563 async fn set_auto_commit_interval_millis(&self, interval_millis: u64) {
1564 if interval_millis < MIN_AUTOCOMMIT_INTERVAL_MILLIS {
1565 return;
1566 }
1567 self.consumer_config.mut_from_ref().auto_commit_interval_millis = interval_millis;
1568 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1569 impl_.set_auto_commit_interval_millis(interval_millis);
1570 }
1571 }
1572
1573 async fn offset_for_timestamp(&self, message_queue: &MessageQueue, timestamp: u64) -> RocketMQResult<i64> {
1574 let wrapped_mq = self.queue_with_namespace(message_queue);
1575 self.try_impl_()?.offset_for_timestamp(&wrapped_mq, timestamp).await
1576 }
1577
1578 async fn earliest_msg_store_time(&self, message_queue: &MessageQueue) -> RocketMQResult<i64> {
1579 let wrapped_mq = self.queue_with_namespace(message_queue);
1580 self.try_impl_()?.earliest_msg_store_time(&wrapped_mq).await
1581 }
1582
1583 async fn max_offset(&self, message_queue: &MessageQueue) -> RocketMQResult<i64> {
1584 let wrapped_mq = self.queue_with_namespace(message_queue);
1585 self.try_impl_()?.max_offset_public(&wrapped_mq).await
1586 }
1587
1588 async fn min_offset(&self, message_queue: &MessageQueue) -> RocketMQResult<i64> {
1589 let wrapped_mq = self.queue_with_namespace(message_queue);
1590 self.try_impl_()?.min_offset_public(&wrapped_mq).await
1591 }
1592
1593 async fn pause(&self, message_queues: Vec<MessageQueue>) {
1594 let wrapped_queues: Vec<_> = message_queues.iter().map(|mq| self.queue_with_namespace(mq)).collect();
1595
1596 match self.try_impl_() {
1597 Ok(impl_) => impl_.pause(&wrapped_queues).await,
1598 Err(e) => tracing::warn!("pause failed: {}", e),
1599 }
1600 }
1601
1602 async fn resume(&self, message_queues: Vec<MessageQueue>) {
1603 let wrapped_queues: Vec<_> = message_queues.iter().map(|mq| self.queue_with_namespace(mq)).collect();
1604
1605 match self.try_impl_() {
1606 Ok(impl_) => impl_.resume(&wrapped_queues).await,
1607 Err(e) => tracing::warn!("resume failed: {}", e),
1608 }
1609 }
1610
1611 async fn is_paused(&self, message_queue: &MessageQueue) -> bool {
1612 let wrapped_mq = self.queue_with_namespace(message_queue);
1613 match self.try_impl_() {
1614 Ok(impl_) => impl_.is_paused(&wrapped_mq).await,
1615 Err(e) => {
1616 tracing::warn!("is_paused failed: {}", e);
1617 false
1618 }
1619 }
1620 }
1621
1622 async fn seek(&self, message_queue: &MessageQueue, offset: i64) -> RocketMQResult<()> {
1623 let wrapped_mq = self.queue_with_namespace(message_queue);
1624 self.try_impl_()?.seek(&wrapped_mq, offset).await
1625 }
1626
1627 async fn seek_to_begin(&self, message_queue: &MessageQueue) -> RocketMQResult<()> {
1628 let wrapped_mq = self.queue_with_namespace(message_queue);
1629 self.try_impl_()?.seek_to_begin(&wrapped_mq).await
1630 }
1631
1632 async fn seek_to_end(&self, message_queue: &MessageQueue) -> RocketMQResult<()> {
1633 let wrapped_mq = self.queue_with_namespace(message_queue);
1634 self.try_impl_()?.seek_to_end(&wrapped_mq).await
1635 }
1636
1637 async fn update_name_server_address(&self, name_server_address: &str) {
1638 self.client_config
1639 .mut_from_ref()
1640 .set_namesrv_addr(CheetahString::from_string(name_server_address.to_string()));
1641
1642 if let Some(impl_) = self.default_lite_pull_consumer_impl.get() {
1643 let addresses: Vec<String> = name_server_address
1644 .split(';')
1645 .map(|s| s.trim().to_string())
1646 .filter(|s| !s.is_empty())
1647 .collect();
1648 impl_.update_name_server_address(addresses).await;
1649 }
1650 }
1651
1652 async fn register_topic_message_queue_change_listener<TL>(&self, topic: &str, listener: TL) -> RocketMQResult<()>
1653 where
1654 TL: TopicMessageQueueChangeListener + 'static,
1655 {
1656 let wrapped_topic = self.with_namespace(topic);
1657 let listener_arc: Arc<dyn TopicMessageQueueChangeListener + Send + Sync> = Arc::new(listener);
1658 self.try_impl_()?
1659 .register_topic_message_queue_change_listener(wrapped_topic, listener_arc)
1660 .await
1661 }
1662}
1663
1664impl MQConsumer for DefaultLitePullConsumer {
1665 async fn create_topic(
1666 &mut self,
1667 key: &str,
1668 new_topic: &str,
1669 queue_num: i32,
1670 attributes: HashMap<String, String>,
1671 ) -> RocketMQResult<()> {
1672 DefaultLitePullConsumer::create_topic(self, key, new_topic, queue_num, attributes).await
1673 }
1674
1675 async fn create_topic_with_flag(
1676 &mut self,
1677 key: &str,
1678 new_topic: &str,
1679 queue_num: i32,
1680 topic_sys_flag: i32,
1681 attributes: HashMap<String, String>,
1682 ) -> RocketMQResult<()> {
1683 DefaultLitePullConsumer::create_topic_with_flag(self, key, new_topic, queue_num, topic_sys_flag, attributes)
1684 .await
1685 }
1686
1687 async fn query_message(
1688 &mut self,
1689 topic: &str,
1690 key: &str,
1691 max_num: i32,
1692 begin: u64,
1693 end: u64,
1694 ) -> RocketMQResult<QueryResult> {
1695 DefaultLitePullConsumer::query_message(self, topic, key, max_num, begin, end).await
1696 }
1697
1698 async fn view_message(&mut self, topic: &str, msg_id: &str) -> RocketMQResult<MessageExt> {
1699 DefaultLitePullConsumer::view_message(self, topic, msg_id).await
1700 }
1701
1702 async fn send_message_back(&mut self, msg: MessageExt, delay_level: i32, broker_name: &str) -> RocketMQResult<()> {
1703 Err(crate::mq_client_err!(
1706 -1,
1707 "sendMessageBack is not supported in lite pull consumer"
1708 ))
1709 }
1710
1711 async fn fetch_subscribe_message_queues(&mut self, topic: &str) -> RocketMQResult<Vec<MessageQueue>> {
1712 let queues = self.fetch_message_queues(topic).await?;
1713 Ok(queues.into_iter().collect())
1714 }
1715
1716 async fn search_offset(&mut self, mq: &MessageQueue, timestamp: u64) -> RocketMQResult<i64> {
1717 <Self as LitePullConsumer>::offset_for_timestamp(self, mq, timestamp).await
1718 }
1719
1720 async fn max_offset(&mut self, mq: &MessageQueue) -> RocketMQResult<i64> {
1721 <Self as LitePullConsumer>::max_offset(self, mq).await
1722 }
1723
1724 async fn min_offset(&mut self, mq: &MessageQueue) -> RocketMQResult<i64> {
1725 <Self as LitePullConsumer>::min_offset(self, mq).await
1726 }
1727
1728 async fn earliest_msg_store_time(&mut self, mq: &MessageQueue) -> RocketMQResult<i64> {
1729 <Self as LitePullConsumer>::earliest_msg_store_time(self, mq).await
1730 }
1731}
1732
1733#[cfg(test)]
1734mod tests {
1735 use std::any::Any;
1736 use std::sync::atomic::AtomicUsize;
1737 use std::sync::atomic::Ordering;
1738 use std::sync::Mutex as StdMutex;
1739
1740 use super::*;
1741 use crate::base::access_channel::AccessChannel;
1742 use crate::common::acl_client_rpc_hook::AclClientRPCHook;
1743 use crate::common::session_credentials::SessionCredentials;
1744 use crate::consumer::mq_consumer_inner::MQConsumerInner;
1745 use crate::consumer::rebalance_strategy::allocate_message_queue_averagely_by_circle::AllocateMessageQueueAveragelyByCircle;
1746 use crate::consumer::store::read_offset_type::ReadOffsetType;
1747
1748 #[derive(Default)]
1749 struct CapturingTraceDispatcher {
1750 start_count: AtomicUsize,
1751 shutdown_count: AtomicUsize,
1752 append_count: AtomicUsize,
1753 last_name_srv_addr: StdMutex<Option<String>>,
1754 last_access_channel: StdMutex<Option<AccessChannel>>,
1755 }
1756
1757 impl TraceDispatcher for CapturingTraceDispatcher {
1758 fn start(&self, name_srv_addr: &str, access_channel: AccessChannel) -> RocketMQResult<()> {
1759 self.start_count.fetch_add(1, Ordering::SeqCst);
1760 *self.last_name_srv_addr.lock().expect("name server lock") = Some(name_srv_addr.to_string());
1761 *self.last_access_channel.lock().expect("access channel lock") = Some(access_channel);
1762 Ok(())
1763 }
1764
1765 fn append(&self, _ctx: &dyn Any) -> bool {
1766 self.append_count.fetch_add(1, Ordering::SeqCst);
1767 true
1768 }
1769
1770 fn flush(&self) -> RocketMQResult<()> {
1771 Ok(())
1772 }
1773
1774 fn shutdown(&self) {
1775 self.shutdown_count.fetch_add(1, Ordering::SeqCst);
1776 }
1777
1778 fn as_any(&self) -> &dyn Any {
1779 self
1780 }
1781
1782 fn as_mut_any(&mut self) -> &mut dyn Any {
1783 self
1784 }
1785 }
1786
1787 struct NoopMessageQueueListener;
1788
1789 impl MessageQueueListener for NoopMessageQueueListener {
1790 fn message_queue_changed(
1791 &self,
1792 _topic: &str,
1793 _mq_all: &HashSet<MessageQueue>,
1794 _mq_assigned: &HashSet<MessageQueue>,
1795 ) {
1796 }
1797 }
1798
1799 fn new_unstarted_consumer() -> DefaultLitePullConsumer {
1800 DefaultLitePullConsumer::builder()
1801 .consumer_group("lite_pull_group")
1802 .build()
1803 .expect("builder should create consumer")
1804 }
1805
1806 fn new_namespaced_consumer_with_impl() -> (DefaultLitePullConsumer, ArcMut<DefaultLitePullConsumerImpl>) {
1807 let consumer = DefaultLitePullConsumer::builder()
1808 .consumer_group("lite_pull_namespace_group")
1809 .namespace("ns")
1810 .build()
1811 .expect("builder should create namespaced consumer");
1812 let mut impl_ = ArcMut::new(DefaultLitePullConsumerImpl::new(
1813 consumer.client_config.clone(),
1814 consumer.consumer_config.clone(),
1815 ));
1816 let wrapper = impl_.clone();
1817 impl_.set_default_lite_pull_consumer_impl(wrapper);
1818 if consumer.default_lite_pull_consumer_impl.set(impl_.clone()).is_err() {
1819 panic!("test consumer impl should be set once");
1820 }
1821
1822 (consumer, impl_)
1823 }
1824
1825 #[tokio::test]
1826 async fn assignment_before_start_returns_not_initialized_error() {
1827 let consumer = new_unstarted_consumer();
1828
1829 let error = consumer
1830 .assignment()
1831 .await
1832 .expect_err("assignment before start should fail");
1833
1834 assert!(error.to_string().contains("DefaultLitePullConsumer not started"));
1835 }
1836
1837 #[tokio::test]
1838 async fn consumer_running_info_before_start_returns_not_initialized_error() {
1839 let consumer = new_unstarted_consumer();
1840
1841 let error = consumer
1842 .consumer_running_info()
1843 .await
1844 .expect_err("running info before start should fail");
1845
1846 assert!(error.to_string().contains("DefaultLitePullConsumer not started"));
1847 }
1848
1849 #[tokio::test]
1850 async fn subscribe_before_start_initializes_impl_and_records_subscription_like_java() {
1851 let consumer = DefaultLitePullConsumer::builder()
1852 .consumer_group("lite_pull_pre_start_subscribe_group")
1853 .namespace("ns")
1854 .build()
1855 .expect("builder should create consumer");
1856
1857 consumer
1858 .subscribe_with_expression("TopicPreStart", "TagA")
1859 .await
1860 .expect("LitePull should accept subscribe before start like Java");
1861
1862 assert!(!consumer.is_running().await);
1863 let impl_ = consumer
1864 .try_impl_()
1865 .expect("pre-start subscribe should initialize the implementation");
1866 let subscriptions = impl_.subscriptions();
1867 let subscription = subscriptions
1868 .iter()
1869 .find(|subscription| subscription.topic.as_str() == "ns%TopicPreStart")
1870 .expect("pre-start subscribe should be stored in rebalance subscriptions");
1871
1872 assert_eq!(subscription.sub_string.as_str(), "TagA");
1873 }
1874
1875 #[tokio::test]
1876 async fn initialization_propagates_rpc_hook_to_impl() {
1877 let rpc_hook = Arc::new(AclClientRPCHook::new(SessionCredentials::with_keys(
1878 "access_key",
1879 "secret_key",
1880 )));
1881 let consumer = DefaultLitePullConsumer::builder()
1882 .consumer_group("lite_pull_rpc_hook_group")
1883 .rpc_hook(rpc_hook)
1884 .build()
1885 .expect("builder should create consumer with RPC hook");
1886
1887 let impl_ = consumer
1888 .get_or_init_impl()
1889 .await
1890 .expect("impl initialization should keep RPC hook");
1891
1892 assert!(impl_.has_rpc_hook(), "LitePull impl should retain builder RPC hook");
1893 }
1894
1895 #[tokio::test]
1896 async fn mq_consumer_offset_facade_delegates_to_lite_pull_impl_path() {
1897 let mut consumer = new_unstarted_consumer();
1898 let mq = MessageQueue::from_parts("TopicLite", "broker-a", 0);
1899
1900 let search_error = <DefaultLitePullConsumer as MQConsumer>::search_offset(&mut consumer, &mq, 1)
1901 .await
1902 .expect_err("searchOffset should enter LitePull path and fail because the consumer is not started");
1903 let max_error = <DefaultLitePullConsumer as MQConsumer>::max_offset(&mut consumer, &mq)
1904 .await
1905 .expect_err("maxOffset should enter LitePull path and fail because the consumer is not started");
1906 let min_error = <DefaultLitePullConsumer as MQConsumer>::min_offset(&mut consumer, &mq)
1907 .await
1908 .expect_err("minOffset should enter LitePull path and fail because the consumer is not started");
1909 let earliest_error = <DefaultLitePullConsumer as MQConsumer>::earliest_msg_store_time(&mut consumer, &mq)
1910 .await
1911 .expect_err("earliestMsgStoreTime should enter LitePull path and fail because the consumer is not started");
1912
1913 for error in [search_error, max_error, min_error, earliest_error] {
1914 let message = error.to_string();
1915 assert!(message.contains("DefaultLitePullConsumer not started"));
1916 assert!(!message.contains("not supported by this MQConsumer implementation"));
1917 }
1918 }
1919
1920 #[tokio::test]
1921 async fn mq_consumer_admin_facade_delegates_to_lite_pull_impl_path() {
1922 let mut consumer = new_unstarted_consumer();
1923
1924 let create_error = <DefaultLitePullConsumer as MQConsumer>::create_topic(
1925 &mut consumer,
1926 TopicValidator::AUTO_CREATE_TOPIC_KEY_TOPIC,
1927 "TopicLiteAdmin",
1928 1,
1929 HashMap::new(),
1930 )
1931 .await
1932 .expect_err("createTopic should enter LitePull path and fail because the consumer is not started");
1933 let create_with_flag_error = <DefaultLitePullConsumer as MQConsumer>::create_topic_with_flag(
1934 &mut consumer,
1935 TopicValidator::AUTO_CREATE_TOPIC_KEY_TOPIC,
1936 "TopicLiteAdmin",
1937 1,
1938 0,
1939 HashMap::new(),
1940 )
1941 .await
1942 .expect_err("createTopicWithFlag should enter LitePull path and fail because the consumer is not started");
1943 let query_error =
1944 <DefaultLitePullConsumer as MQConsumer>::query_message(&mut consumer, "TopicLiteAdmin", "key", 32, 0, 1)
1945 .await
1946 .expect_err("queryMessage should enter LitePull path and fail because the consumer is not started");
1947 let view_error =
1948 <DefaultLitePullConsumer as MQConsumer>::view_message(&mut consumer, "TopicLiteAdmin", "not-a-msg-id")
1949 .await
1950 .expect_err("viewMessage should enter LitePull path and fail because the consumer is not started");
1951
1952 for error in [create_error, create_with_flag_error, query_error, view_error] {
1953 let message = error.to_string();
1954 assert!(message.contains("DefaultLitePullConsumer not started"));
1955 assert!(!message.contains("not supported by this MQConsumer implementation"));
1956 }
1957 }
1958
1959 #[tokio::test]
1960 async fn consumer_running_info_facade_returns_lite_pull_snapshot() {
1961 let (consumer, _impl_) = new_namespaced_consumer_with_impl();
1962 consumer
1963 .subscribe_with_expression("TopicLiteRunningInfo", "TagA")
1964 .await
1965 .expect("subscribe should update running-info subscriptions");
1966 consumer.set_pull_batch_size(17).await;
1967 consumer.set_auto_commit(false).await;
1968 consumer.set_auto_commit_interval_millis(2_000).await;
1969
1970 let info = consumer
1971 .consumer_running_info()
1972 .await
1973 .expect("running info facade should delegate to impl");
1974
1975 assert_eq!(
1976 info.properties
1977 .get(ConsumerRunningInfo::PROP_CONSUME_TYPE)
1978 .map(String::as_str),
1979 Some("CONSUME_ACTIVELY")
1980 );
1981 assert_eq!(
1982 info.properties.get("consumerGroup").map(String::as_str),
1983 Some("lite_pull_namespace_group")
1984 );
1985 assert_eq!(info.properties.get("pullBatchSize").map(String::as_str), Some("17"));
1986 assert_eq!(info.properties.get("autoCommit").map(String::as_str), Some("false"));
1987 assert_eq!(
1988 info.properties.get("autoCommitIntervalMillis").map(String::as_str),
1989 Some("2000")
1990 );
1991 assert!(info
1992 .subscription_set
1993 .iter()
1994 .any(|subscription| subscription.topic.as_str() == "ns%TopicLiteRunningInfo"
1995 && subscription.sub_string.as_str() == "TagA"));
1996 }
1997
1998 #[tokio::test]
1999 async fn assign_surfaces_impl_errors_like_java() {
2000 let (consumer, _impl_) = new_namespaced_consumer_with_impl();
2001
2002 let error = consumer
2003 .assign(Vec::new())
2004 .await
2005 .expect_err("empty manual assignment should be rejected");
2006
2007 assert!(error.to_string().contains("Message queues can not be null or empty."));
2008 }
2009
2010 #[tokio::test]
2011 async fn offset_metadata_queries_before_start_return_not_initialized_error() {
2012 let consumer = new_unstarted_consumer();
2013 let queue = MessageQueue::from_parts("TopicA", "broker-a", 0);
2014
2015 let earliest_error = consumer
2016 .earliest_msg_store_time(&queue)
2017 .await
2018 .expect_err("earliest store time before start should fail");
2019 let max_error = consumer
2020 .max_offset(&queue)
2021 .await
2022 .expect_err("max offset before start should fail");
2023 let min_error = consumer
2024 .min_offset(&queue)
2025 .await
2026 .expect_err("min offset before start should fail");
2027
2028 assert!(earliest_error
2029 .to_string()
2030 .contains("DefaultLitePullConsumer not started"));
2031 assert!(max_error.to_string().contains("DefaultLitePullConsumer not started"));
2032 assert!(min_error.to_string().contains("DefaultLitePullConsumer not started"));
2033 }
2034
2035 #[tokio::test]
2036 async fn poll_before_start_returns_empty_vec_without_panic() {
2037 let consumer = new_unstarted_consumer();
2038
2039 assert!(consumer.poll_zero_copy().await.is_empty());
2040 assert!(consumer.poll_with_timeout_zero_copy(1).await.is_empty());
2041 }
2042
2043 #[tokio::test]
2044 async fn lite_pull_facade_namespace_subscribe_wraps_builder_namespace_like_java() {
2045 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2046
2047 assert_eq!(consumer.namespace().as_deref(), Some("ns"));
2048 consumer
2049 .subscribe_with_expression("TopicA", "TagA")
2050 .await
2051 .expect("subscribe should succeed with injected impl");
2052
2053 let subscriptions = impl_.subscriptions();
2054 let subscription = subscriptions
2055 .iter()
2056 .find(|subscription| subscription.topic.as_str() == "ns%TopicA")
2057 .expect("namespaced topic should be subscribed");
2058 assert_eq!(subscription.sub_string.as_str(), "TagA");
2059 assert!(!subscriptions
2060 .iter()
2061 .any(|subscription| subscription.topic.as_str() == "TopicA"));
2062 }
2063
2064 #[tokio::test]
2065 async fn subscriptions_for_heartbeat_returns_current_rebalance_subscriptions_like_java_getter() {
2066 let (consumer, _impl_) = new_namespaced_consumer_with_impl();
2067
2068 assert!(consumer.subscriptions_for_heartbeat().await.is_empty());
2069
2070 consumer
2071 .subscribe_with_expression("TopicA", "TagA")
2072 .await
2073 .expect("subscribe should succeed with injected impl");
2074
2075 let subscriptions = consumer.subscriptions_for_heartbeat().await;
2076 assert_eq!(subscriptions.len(), 1);
2077 let subscription = subscriptions.iter().next().expect("subscription should exist");
2078 assert_eq!(subscription.topic.as_str(), "ns%TopicA");
2079 assert_eq!(subscription.sub_string.as_str(), "TagA");
2080 }
2081
2082 #[tokio::test]
2083 async fn lite_pull_java_getter_aliases_delegate_to_config() {
2084 let consumer = new_unstarted_consumer();
2085
2086 assert_eq!(consumer.get_message_model().await, consumer.message_model().await);
2087 assert_eq!(
2088 consumer.get_consume_from_where().await,
2089 consumer.consume_from_where().await
2090 );
2091 assert_eq!(
2092 consumer.get_consume_timestamp().await,
2093 consumer.consume_timestamp().await
2094 );
2095 assert_eq!(
2096 consumer.get_allocate_message_queue_strategy().await.get_name(),
2097 consumer.allocate_message_queue_strategy().await.get_name()
2098 );
2099 assert_eq!(
2100 consumer.get_offset_store().await.is_some(),
2101 consumer.offset_store().await.is_some()
2102 );
2103 assert_eq!(
2104 consumer.get_topic_metadata_check_interval_millis().await,
2105 consumer.topic_metadata_check_interval_millis().await
2106 );
2107 assert_eq!(
2108 consumer.get_poll_timeout_millis().await,
2109 consumer.poll_timeout_millis().await
2110 );
2111 assert_eq!(
2112 consumer.get_consumer_timeout_millis_when_suspend().await,
2113 consumer.consumer_timeout_millis_when_suspend().await
2114 );
2115 assert_eq!(
2116 consumer.get_consumer_pull_timeout_millis().await,
2117 consumer.consumer_pull_timeout_millis().await
2118 );
2119 assert_eq!(consumer.get_pull_batch_size().await, consumer.pull_batch_size().await);
2120 assert_eq!(
2121 consumer.get_pull_threshold_for_all().await,
2122 consumer.pull_threshold_for_all().await
2123 );
2124 assert_eq!(
2125 consumer.get_pull_threshold_for_queue().await,
2126 consumer.pull_threshold_for_queue().await
2127 );
2128 assert_eq!(
2129 consumer.get_pull_threshold_size_for_queue().await,
2130 consumer.pull_threshold_size_for_queue().await
2131 );
2132 assert_eq!(
2133 consumer.get_auto_commit_interval_millis().await,
2134 consumer.auto_commit_interval_millis().await
2135 );
2136 }
2137
2138 #[tokio::test]
2139 async fn set_sub_expression_for_assign_surfaces_impl_errors_like_java() {
2140 let (consumer, _impl_) = new_namespaced_consumer_with_impl();
2141
2142 let error = consumer
2143 .set_sub_expression_for_assign("TopicA", " ")
2144 .await
2145 .expect_err("blank assign filter should be rejected");
2146 assert!(error.to_string().contains("subExpression can not be null or empty."));
2147
2148 consumer
2149 .set_sub_expression_for_assign("TopicA", "TagA")
2150 .await
2151 .expect("valid assign filter should be accepted before start");
2152 }
2153
2154 #[tokio::test]
2155 async fn set_auto_commit_updates_initialized_impl_like_java_facade_reference() {
2156 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2157
2158 assert!(consumer.is_auto_commit().await);
2159 assert!(impl_.is_auto_commit());
2160
2161 consumer.set_auto_commit(false).await;
2162
2163 assert!(!consumer.is_auto_commit().await);
2164 assert!(!impl_.is_auto_commit());
2165
2166 consumer.set_auto_commit(true).await;
2167
2168 assert!(consumer.is_auto_commit().await);
2169 assert!(impl_.is_auto_commit());
2170 }
2171
2172 #[tokio::test]
2173 async fn set_auto_commit_interval_updates_initialized_impl_and_ignores_invalid_like_java() {
2174 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2175
2176 assert_eq!(consumer.auto_commit_interval_millis().await, 5000);
2177 assert_eq!(impl_.auto_commit_interval_millis(), 5000);
2178
2179 consumer.set_auto_commit_interval_millis(2000).await;
2180
2181 assert_eq!(consumer.auto_commit_interval_millis().await, 2000);
2182 assert_eq!(impl_.auto_commit_interval_millis(), 2000);
2183
2184 consumer
2185 .set_auto_commit_interval_millis(MIN_AUTOCOMMIT_INTERVAL_MILLIS - 1)
2186 .await;
2187
2188 assert_eq!(consumer.auto_commit_interval_millis().await, 2000);
2189 assert_eq!(impl_.auto_commit_interval_millis(), 2000);
2190 }
2191
2192 #[tokio::test]
2193 async fn set_unit_mode_updates_initialized_impl_and_heartbeat_source_like_java() {
2194 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2195
2196 assert!(!consumer.is_unit_mode().await);
2197 assert!(!impl_.is_unit_mode());
2198 assert!(!MQConsumerInner::is_unit_mode(impl_.as_ref()));
2199
2200 consumer.set_unit_mode(true).await;
2201
2202 assert!(consumer.is_unit_mode().await);
2203 assert!(impl_.is_unit_mode());
2204 assert!(MQConsumerInner::is_unit_mode(impl_.as_ref()));
2205 }
2206
2207 #[test]
2208 fn set_consumer_group_updates_initialized_impl_and_rebalance_before_start_like_java() {
2209 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2210
2211 consumer
2212 .set_consumer_group("lite_pull_updated_group")
2213 .expect("consumer group should be mutable before start");
2214
2215 assert_eq!(consumer.consumer_group().as_str(), "lite_pull_updated_group");
2216 assert_eq!(impl_.consumer_group_config().as_str(), "lite_pull_updated_group");
2217 assert_eq!(
2218 MQConsumerInner::group_name(impl_.as_ref()).as_str(),
2219 "lite_pull_updated_group"
2220 );
2221 assert_eq!(
2222 impl_.rebalance_consumer_group_name().as_deref(),
2223 Some("lite_pull_updated_group")
2224 );
2225 }
2226
2227 #[test]
2228 fn start_namespace_wraps_consumer_group_like_java_lite_pull_start() {
2229 let (consumer, _impl_) = new_namespaced_consumer_with_impl();
2230
2231 assert_eq!(
2232 consumer.consumer_group_with_namespace().as_str(),
2233 "ns%lite_pull_namespace_group"
2234 );
2235
2236 consumer
2237 .set_consumer_group("ns%lite_pull_namespace_group")
2238 .expect("pre-wrapped group should be accepted before start");
2239
2240 assert_eq!(
2241 consumer.consumer_group_with_namespace().as_str(),
2242 "ns%lite_pull_namespace_group"
2243 );
2244 }
2245
2246 #[tokio::test]
2247 async fn set_message_queue_listener_updates_initialized_impl_like_java() {
2248 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2249
2250 assert!(consumer.message_queue_listener().await.is_none());
2251 assert!(impl_.message_queue_listener().is_none());
2252
2253 let listener: ArcMessageQueueListener = Arc::new(NoopMessageQueueListener);
2254 consumer.set_message_queue_listener(Some(listener.clone())).await;
2255
2256 let facade_listener = consumer
2257 .message_queue_listener()
2258 .await
2259 .expect("facade should return configured listener");
2260 let impl_listener = impl_
2261 .message_queue_listener()
2262 .expect("impl should receive configured listener");
2263 assert!(Arc::ptr_eq(&facade_listener, &listener));
2264 assert!(Arc::ptr_eq(&impl_listener, &listener));
2265
2266 consumer.set_message_queue_listener(None).await;
2267
2268 assert!(consumer.message_queue_listener().await.is_none());
2269 assert!(impl_.message_queue_listener().is_none());
2270 }
2271
2272 #[tokio::test]
2273 async fn set_offset_store_updates_initialized_impl_and_rebalance_like_java() {
2274 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2275 let queue = MessageQueue::from_parts("TopicA", "broker-a", 0);
2276 let offset_store = ArcMut::new(OffsetStore::new_test());
2277
2278 assert!(consumer.offset_store().await.is_none());
2279 assert!(impl_.offset_store().is_none());
2280 assert!(!impl_.rebalance_has_offset_store());
2281
2282 consumer
2283 .set_offset_store(Some(offset_store.clone()))
2284 .await
2285 .expect("offset store should be mutable before start");
2286 offset_store.update_offset(&queue, 42, false).await;
2287
2288 let facade_store = consumer
2289 .offset_store()
2290 .await
2291 .expect("facade should expose configured offset store");
2292 let impl_store = impl_
2293 .offset_store()
2294 .expect("impl should receive configured offset store");
2295 assert_eq!(
2296 facade_store.read_offset(&queue, ReadOffsetType::ReadFromMemory).await,
2297 42
2298 );
2299 assert_eq!(impl_store.read_offset(&queue, ReadOffsetType::ReadFromMemory).await, 42);
2300 assert!(impl_.rebalance_has_offset_store());
2301
2302 consumer
2303 .set_offset_store(None)
2304 .await
2305 .expect("offset store should be clearable before start");
2306
2307 assert!(consumer.offset_store().await.is_none());
2308 assert!(impl_.offset_store().is_none());
2309 assert!(!impl_.rebalance_has_offset_store());
2310 }
2311
2312 #[tokio::test]
2313 async fn set_allocate_message_queue_strategy_updates_initialized_impl_and_rebalance_like_java() {
2314 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2315
2316 assert_eq!(consumer.allocate_message_queue_strategy().await.get_name(), "AVG");
2317 assert_eq!(impl_.allocate_message_queue_strategy().get_name(), "AVG");
2318 assert_eq!(impl_.rebalance_allocate_message_queue_strategy_name(), None);
2319
2320 consumer
2321 .set_allocate_message_queue_strategy(Arc::new(AllocateMessageQueueAveragelyByCircle))
2322 .await;
2323
2324 assert_eq!(
2325 consumer.allocate_message_queue_strategy().await.get_name(),
2326 "AVG_BY_CIRCLE"
2327 );
2328 assert_eq!(impl_.allocate_message_queue_strategy().get_name(), "AVG_BY_CIRCLE");
2329 assert_eq!(
2330 impl_.rebalance_allocate_message_queue_strategy_name(),
2331 Some("AVG_BY_CIRCLE")
2332 );
2333 }
2334
2335 #[tokio::test]
2336 #[allow(deprecated)]
2337 async fn core_runtime_config_setters_update_initialized_impl_like_java_facade_reference() {
2338 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2339
2340 assert_eq!(consumer.message_model().await, MessageModel::Clustering);
2341 assert_eq!(impl_.message_model_config(), MessageModel::Clustering);
2342 assert_eq!(MQConsumerInner::message_model(impl_.as_ref()), MessageModel::Clustering);
2343
2344 consumer.set_message_model(MessageModel::Broadcasting).await;
2345
2346 assert_eq!(consumer.message_model().await, MessageModel::Broadcasting);
2347 assert_eq!(impl_.message_model_config(), MessageModel::Broadcasting);
2348 assert_eq!(
2349 MQConsumerInner::message_model(impl_.as_ref()),
2350 MessageModel::Broadcasting
2351 );
2352
2353 assert_eq!(
2354 consumer.consume_from_where().await,
2355 ConsumeFromWhere::ConsumeFromLastOffset
2356 );
2357 consumer
2358 .set_consume_from_where(ConsumeFromWhere::ConsumeFromFirstOffset)
2359 .await
2360 .expect("valid Java LitePull consumeFromWhere should be accepted");
2361
2362 assert_eq!(
2363 consumer.consume_from_where().await,
2364 ConsumeFromWhere::ConsumeFromFirstOffset
2365 );
2366 assert_eq!(
2367 impl_.consume_from_where_config(),
2368 ConsumeFromWhere::ConsumeFromFirstOffset
2369 );
2370 assert_eq!(
2371 MQConsumerInner::consume_from_where(impl_.as_ref()),
2372 ConsumeFromWhere::ConsumeFromFirstOffset
2373 );
2374
2375 let error = consumer
2376 .set_consume_from_where(ConsumeFromWhere::ConsumeFromMaxOffset)
2377 .await
2378 .expect_err("Java LitePull rejects legacy consumeFromWhere values");
2379 assert!(error.to_string().contains("Invalid ConsumeFromWhere Value"));
2380 assert_eq!(
2381 consumer.consume_from_where().await,
2382 ConsumeFromWhere::ConsumeFromFirstOffset
2383 );
2384
2385 let timestamp = CheetahString::from_static_str("20250102030405");
2386 consumer.set_consume_timestamp(Some(timestamp.clone())).await;
2387
2388 assert_eq!(consumer.consume_timestamp().await, Some(timestamp.clone()));
2389 assert_eq!(impl_.consume_timestamp(), Some(timestamp));
2390
2391 assert_eq!(consumer.topic_metadata_check_interval_millis().await, 30_000);
2392 assert_eq!(impl_.topic_metadata_check_interval_millis(), 30_000);
2393
2394 consumer.set_topic_metadata_check_interval_millis(12_345).await;
2395
2396 assert_eq!(consumer.topic_metadata_check_interval_millis().await, 12_345);
2397 assert_eq!(impl_.topic_metadata_check_interval_millis(), 12_345);
2398 }
2399
2400 #[tokio::test]
2401 async fn set_poll_timeout_updates_initialized_impl_like_java_facade_reference() {
2402 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2403
2404 assert_eq!(consumer.poll_timeout_millis().await, 5000);
2405 assert_eq!(impl_.poll_timeout_millis(), 5000);
2406
2407 consumer.set_poll_timeout_millis(1234).await;
2408
2409 assert_eq!(consumer.poll_timeout_millis().await, 1234);
2410 assert_eq!(impl_.poll_timeout_millis(), 1234);
2411 }
2412
2413 #[tokio::test]
2414 async fn long_polling_timeout_setters_update_initialized_impl_like_java_facade_reference() {
2415 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2416
2417 assert_eq!(consumer.broker_suspend_max_time_millis().await, 20_000);
2418 assert_eq!(impl_.broker_suspend_max_time_millis(), 20_000);
2419 assert_eq!(consumer.consumer_timeout_millis_when_suspend().await, 30_000);
2420 assert_eq!(impl_.consumer_timeout_millis_when_suspend(), 30_000);
2421 assert_eq!(consumer.consumer_pull_timeout_millis().await, 10_000);
2422 assert_eq!(impl_.consumer_pull_timeout_millis(), 10_000);
2423
2424 consumer.set_broker_suspend_max_time_millis(11_111).await;
2425 consumer.set_consumer_timeout_millis_when_suspend(22_222).await;
2426 consumer.set_consumer_pull_timeout_millis(12_345).await;
2427
2428 assert_eq!(consumer.broker_suspend_max_time_millis().await, 11_111);
2429 assert_eq!(impl_.broker_suspend_max_time_millis(), 11_111);
2430 assert_eq!(consumer.consumer_timeout_millis_when_suspend().await, 22_222);
2431 assert_eq!(impl_.consumer_timeout_millis_when_suspend(), 22_222);
2432 assert_eq!(consumer.consumer_pull_timeout_millis().await, 12_345);
2433 assert_eq!(impl_.consumer_pull_timeout_millis(), 12_345);
2434 }
2435
2436 #[tokio::test]
2437 async fn pull_flow_control_setters_update_initialized_impl_like_java_facade_reference() {
2438 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2439
2440 consumer.set_pull_batch_size(64).await;
2441 consumer.set_pull_thread_nums(12).await;
2442 consumer.set_pull_threshold_for_all(20_000).await;
2443 consumer.set_pull_threshold_for_queue(2_000).await;
2444 consumer.set_pull_threshold_size_for_queue(256).await;
2445 consumer.set_consume_max_span(4_000).await;
2446
2447 assert_eq!(consumer.pull_batch_size().await, 64);
2448 assert_eq!(impl_.pull_batch_size(), 64);
2449 assert_eq!(consumer.pull_thread_nums().await, 12);
2450 assert_eq!(impl_.pull_thread_nums(), 12);
2451 assert_eq!(consumer.pull_threshold_for_all().await, 20_000);
2452 assert_eq!(impl_.pull_threshold_for_all(), 20_000);
2453 assert_eq!(consumer.pull_threshold_for_queue().await, 2_000);
2454 assert_eq!(impl_.pull_threshold_for_queue(), 2_000);
2455 assert_eq!(consumer.pull_threshold_size_for_queue().await, 256);
2456 assert_eq!(impl_.pull_threshold_size_for_queue(), 256);
2457 assert_eq!(consumer.consume_max_span().await, 4_000);
2458 assert_eq!(impl_.consume_max_span(), 4_000);
2459 }
2460
2461 #[tokio::test]
2462 async fn broker_selection_setters_update_facade_config_like_java() {
2463 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2464
2465 assert!(!consumer.is_connect_broker_by_user().await);
2466 assert_eq!(
2467 consumer.default_broker_id().await,
2468 rocketmq_common::common::mix_all::MASTER_ID
2469 );
2470 assert!(!impl_.is_connect_broker_by_user());
2471 assert_eq!(impl_.default_broker_id(), rocketmq_common::common::mix_all::MASTER_ID);
2472
2473 consumer.set_connect_broker_by_user(true).await;
2474 consumer.set_default_broker_id(3).await;
2475
2476 assert!(consumer.is_connect_broker_by_user().await);
2477 assert_eq!(consumer.default_broker_id().await, 3);
2478 assert!(impl_.is_connect_broker_by_user());
2479 assert_eq!(impl_.default_broker_id(), 3);
2480 }
2481
2482 #[test]
2483 fn lite_pull_facade_namespace_helpers_use_primary_namespace_like_java() {
2484 let (consumer, _) = new_namespaced_consumer_with_impl();
2485 let queue = MessageQueue::from_parts("TopicB", "broker-a", 3);
2486
2487 assert_eq!(consumer.with_namespace("TopicB").as_str(), "ns%TopicB");
2488 assert_eq!(consumer.with_namespace("ns%TopicB").as_str(), "ns%TopicB");
2489 assert_eq!(consumer.without_namespace("ns%TopicB").as_str(), "TopicB");
2490 assert_eq!(consumer.queue_with_namespace(&queue).topic_str(), "ns%TopicB");
2491 assert_eq!(
2492 consumer
2493 .queue_without_namespace(&MessageQueue::from_parts("ns%TopicB", "broker-a", 3))
2494 .topic_str(),
2495 "TopicB"
2496 );
2497 }
2498
2499 #[tokio::test]
2500 async fn trace_config_accessors_match_java_facade_fields() {
2501 let mut consumer = new_unstarted_consumer();
2502
2503 assert!(!consumer.is_enable_msg_trace());
2504 assert!(consumer.customized_trace_topic().is_none());
2505 assert!(consumer.trace_dispatcher().await.is_none());
2506
2507 consumer.set_enable_msg_trace(true);
2508 consumer.set_customized_trace_topic("TraceTopic");
2509
2510 assert!(consumer.is_enable_msg_trace());
2511 assert_eq!(consumer.customized_trace_topic().as_deref(), Some("TraceTopic"));
2512
2513 consumer.clear_customized_trace_topic();
2514
2515 assert!(consumer.customized_trace_topic().is_none());
2516 }
2517
2518 #[tokio::test]
2519 async fn lite_pull_use_tls_facade_updates_shared_impl_config_like_java_client_config() {
2520 let (consumer, impl_) = new_namespaced_consumer_with_impl();
2521
2522 assert!(!consumer.is_use_tls());
2523 assert!(!impl_.client_config.is_use_tls());
2524
2525 consumer.set_use_tls(true).await;
2526
2527 assert!(consumer.is_use_tls());
2528 assert!(consumer.client_config().is_use_tls());
2529 assert!(impl_.client_config.is_use_tls());
2530 }
2531
2532 #[tokio::test]
2533 async fn lite_pull_use_tls_facade_updates_async_trace_dispatcher() {
2534 let dispatcher = Arc::new(AsyncTraceDispatcher::new(
2535 "lite_pull_tls_trace_group",
2536 Type::Consume,
2537 1,
2538 "",
2539 None,
2540 ));
2541 let consumer = DefaultLitePullConsumer::new(
2542 ArcMut::new(ClientConfig::default()),
2543 ArcMut::new(LitePullConsumerConfig {
2544 consumer_group: CheetahString::from_static_str("lite_pull_tls_trace_group"),
2545 ..Default::default()
2546 }),
2547 None,
2548 Some(dispatcher.clone()),
2549 true,
2550 None,
2551 );
2552
2553 assert!(!consumer.is_use_tls());
2554 assert!(!dispatcher.is_use_tls());
2555
2556 consumer.set_use_tls(true).await;
2557
2558 assert!(consumer.is_use_tls());
2559 assert!(dispatcher.is_use_tls());
2560 }
2561
2562 #[tokio::test]
2563 async fn trace_init_uses_configured_batch_num_like_java() {
2564 let mut client_config = ClientConfig::default();
2565 client_config.set_trace_msg_batch_num(6);
2566 let consumer = DefaultLitePullConsumer::new(
2567 ArcMut::new(client_config),
2568 ArcMut::new(LitePullConsumerConfig {
2569 consumer_group: CheetahString::from_static_str("lite_pull_trace_batch_group"),
2570 ..Default::default()
2571 }),
2572 None,
2573 None,
2574 true,
2575 None,
2576 );
2577 let mut impl_ = ArcMut::new(DefaultLitePullConsumerImpl::new(
2578 consumer.client_config.clone(),
2579 consumer.consumer_config.clone(),
2580 ));
2581 let wrapper = impl_.clone();
2582 impl_.set_default_lite_pull_consumer_impl(wrapper);
2583
2584 consumer
2585 .init_trace_dispatcher_internal(&impl_)
2586 .await
2587 .expect("trace init should create dispatcher");
2588 let dispatcher = consumer
2589 .trace_dispatcher
2590 .read()
2591 .await
2592 .as_ref()
2593 .expect("trace dispatcher should be initialized")
2594 .clone();
2595 let async_dispatcher = dispatcher
2596 .as_any()
2597 .downcast_ref::<AsyncTraceDispatcher>()
2598 .expect("default trace dispatcher should be AsyncTraceDispatcher");
2599 assert_eq!(async_dispatcher.batch_num(), 6);
2600 }
2601
2602 #[tokio::test]
2603 async fn trace_init_registers_custom_dispatcher_and_starts_with_client_config() {
2604 let dispatcher = Arc::new(CapturingTraceDispatcher::default());
2605 let mut client_config = ClientConfig::default();
2606 client_config.set_namesrv_addr(CheetahString::from_static_str("127.0.0.1:9876"));
2607 client_config.set_access_channel(AccessChannel::Cloud);
2608
2609 let consumer = DefaultLitePullConsumer::new(
2610 ArcMut::new(client_config),
2611 ArcMut::new(LitePullConsumerConfig {
2612 consumer_group: CheetahString::from_static_str("lite_pull_trace_group"),
2613 ..Default::default()
2614 }),
2615 None,
2616 Some(dispatcher.clone()),
2617 true,
2618 None,
2619 );
2620 let mut impl_ = ArcMut::new(DefaultLitePullConsumerImpl::new(
2621 consumer.client_config.clone(),
2622 consumer.consumer_config.clone(),
2623 ));
2624 let wrapper = impl_.clone();
2625 impl_.set_default_lite_pull_consumer_impl(wrapper);
2626
2627 consumer
2628 .init_trace_dispatcher_internal(&impl_)
2629 .await
2630 .expect("trace init should register hook");
2631 assert_eq!(impl_.consume_message_hook_count(), 1);
2632
2633 consumer.start_trace_dispatcher().await;
2634 assert_eq!(dispatcher.start_count.load(Ordering::SeqCst), 1);
2635 assert_eq!(
2636 dispatcher
2637 .last_name_srv_addr
2638 .lock()
2639 .expect("name server lock")
2640 .as_deref(),
2641 Some("127.0.0.1:9876")
2642 );
2643 assert_eq!(
2644 *dispatcher.last_access_channel.lock().expect("access channel lock"),
2645 Some(AccessChannel::Cloud)
2646 );
2647 }
2648}