Skip to main content

rocketmq_client_rust/producer/
default_mq_producer.rs

1// Copyright 2023 The RocketMQ Rust Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::HashMap;
16use std::collections::HashSet;
17use std::net::SocketAddr;
18use std::sync::Arc;
19
20use crate::ClientError;
21use arc_swap::ArcSwap;
22use cheetah_string::CheetahString;
23use rocketmq_model::common::compression::compression_type::CompressionType;
24use rocketmq_model::common::message::message_batch::MessageBatch;
25use rocketmq_model::common::message::message_client_id_setter::MessageClientIDSetter;
26use rocketmq_model::common::message::message_ext::MessageExt;
27use rocketmq_model::common::message::message_queue::MessageQueue;
28use rocketmq_model::common::message::message_single::Message;
29use rocketmq_model::common::message::MessageConst;
30use rocketmq_model::common::message::MessageTrait;
31use rocketmq_model::common::mix_all;
32use rocketmq_model::common::mix_all::MESSAGE_COMPRESS_LEVEL;
33use rocketmq_model::common::mix_all::MESSAGE_COMPRESS_TYPE;
34use rocketmq_model::common::topic::TopicValidator;
35use rocketmq_protocol::code::response_code::ResponseCode;
36use rocketmq_protocol::common::compression::compressor::Compressor;
37use rocketmq_protocol::common::compression::compressor_factory::CompressorFactory;
38use rocketmq_protocol::protocol::namespace_util::NamespaceUtil;
39use rocketmq_protocol::protocol::remoting_command::RemotingCommand;
40use rocketmq_transport::api::RPCHook;
41use tracing::error;
42
43use crate::base::client_config::ClientConfig;
44use crate::base::query_result::QueryResult;
45use crate::base::validators::Validators;
46use crate::latency::mq_fault_strategy::MQFaultStrategy;
47use crate::producer::default_mq_produce_builder::DefaultMQProducerBuilder;
48use crate::producer::produce_accumulator::ProduceAccumulator;
49use crate::producer::producer_backend::ProducerBackend;
50use crate::producer::producer_impl::default_mq_producer_impl::DefaultMQProducerImpl;
51use crate::producer::send_callback::ArcSendCallback;
52use crate::producer::send_result::SendResult;
53use crate::producer::transaction_send_result::TransactionSendResult;
54use crate::runtime::ClientRuntime;
55use crate::session::ClientSession;
56use crate::session::ClientSessionProvider;
57use crate::trace::async_trace_dispatcher::AsyncTraceDispatcher;
58use crate::trace::hook::default_recall_message_trace_hook::DefaultRecallMessageTraceHook;
59use crate::trace::hook::end_transaction_trace_hook_impl::EndTransactionTraceHookImpl;
60use crate::trace::hook::send_message_trace_hook_impl::SendMessageTraceHookImpl;
61use crate::trace::trace_dispatcher::ArcTraceDispatcher;
62use crate::trace::trace_dispatcher::Type;
63
64pub(crate) const MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM: u32 = 10;
65pub(crate) const MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE: u32 = 1024 * 1024;
66
67/// Clone-shared immutable configuration snapshots.
68struct StableConfig<T> {
69    current: Arc<ArcSwap<T>>,
70}
71
72impl<T> StableConfig<T> {
73    fn new(value: T) -> Self {
74        Self {
75            current: Arc::new(ArcSwap::from_pointee(value)),
76        }
77    }
78
79    fn replace(&self, value: T) {
80        self.current.store(Arc::new(value));
81    }
82
83    fn snapshot(&self) -> Arc<T> {
84        self.current.load_full()
85    }
86}
87
88impl<T: Clone> StableConfig<T> {
89    fn update<R>(&self, update: impl FnOnce(&mut T) -> R) -> R {
90        let mut next = self.snapshot().as_ref().clone();
91        let result = update(&mut next);
92        self.current.store(Arc::new(next));
93        result
94    }
95}
96
97impl<T> Clone for StableConfig<T> {
98    fn clone(&self) -> Self {
99        Self {
100            current: Arc::clone(&self.current),
101        }
102    }
103}
104
105impl<T: Default> Default for StableConfig<T> {
106    fn default() -> Self {
107        Self::new(T::default())
108    }
109}
110
111#[derive(Clone)]
112pub struct ProducerConfig {
113    retry_response_codes: HashSet<i32>,
114    /// Producer group conceptually aggregates all producer instances of exactly same role, which
115    /// is particularly important when transactional messages are involved.
116    ///
117    /// For non-transactional messages, it does not matter as long as it's unique per process.
118    ///
119    /// See [core concepts](https://rocketmq.apache.org/docs/introduction/02concepts) for more discussion.
120    producer_group: CheetahString,
121    /// Topics that need to be initialized for transaction producer
122    topics: Vec<CheetahString>,
123    create_topic_key: CheetahString,
124    /// Number of queues to create per default topic.
125    default_topic_queue_nums: u32,
126    /// Timeout for sending messages (milliseconds).
127    send_msg_timeout: u32,
128    /// Maximum timeout for sending messages per request (milliseconds).
129    /// None means no limit.
130    send_msg_max_timeout_per_request: Option<u32>,
131    /// Compress message body threshold, namely, message body
132    /// larger than 4k will be compressed on default.
133    compress_msg_body_over_howmuch: u32,
134    /// Maximum number of retry to perform internally before claiming sending failure in
135    /// synchronous mode. This may potentially cause message duplication which is up to application
136    /// developers to resolve.
137    retry_times_when_send_failed: u32,
138    /// Maximum number of retry to perform internally before claiming sending failure in
139    /// asynchronous mode.This may potentially cause message duplication which is up to application
140    /// developers to resolve.
141    retry_times_when_send_async_failed: u32,
142    /// Indicate whether to retry another broker on sending failure internally.
143    retry_another_broker_when_not_store_ok: bool,
144    /// Maximum allowed message size in bytes.
145    max_message_size: u32,
146    trace_dispatcher: Option<ArcTraceDispatcher>,
147    /// Switch flag instance for automatic batch message
148    auto_batch: bool,
149    /// Maximum hold time of accumulator in milliseconds.
150    /// None means no delay.
151    batch_max_delay_ms: Option<u32>,
152    /// Maximum accumulation message body size for a single messageAccumulation (bytes).
153    /// None means no limit.
154    batch_max_bytes: Option<u64>,
155    /// Maximum message body size for produceAccumulator (bytes).
156    /// None means no limit.
157    total_batch_max_bytes: Option<u64>,
158    /// Instance for batching message automatically
159    produce_accumulator: Option<Arc<ProduceAccumulator>>,
160    /// Indicate whether to block message when asynchronous sending traffic is too heavy.
161    enable_backpressure_for_async_mode: bool,
162    /// on BackpressureForAsyncMode, limit maximum number of on-going sending async messages
163    /// default is 10000
164    back_pressure_for_async_send_num: u32,
165    /// on BackpressureForAsyncMode, limit maximum message size of on-going sending async messages
166    /// default is 100M
167    back_pressure_for_async_send_size: u32,
168    rpc_hook: Option<Arc<dyn RPCHook>>,
169    compress_level: i32,
170    compress_type: CompressionType,
171    compressor: Option<&'static (dyn Compressor + Send + Sync)>,
172    latency_max: Vec<u64>,
173    not_available_duration: Vec<u64>,
174}
175
176struct CompositeRPCHook {
177    hooks: Vec<Arc<dyn RPCHook>>,
178}
179
180impl CompositeRPCHook {
181    fn chain(first: Arc<dyn RPCHook>, second: Arc<dyn RPCHook>) -> Arc<dyn RPCHook> {
182        Arc::new(Self {
183            hooks: vec![first, second],
184        })
185    }
186}
187
188impl RPCHook for CompositeRPCHook {
189    fn do_before_request(
190        &self,
191        remote_addr: SocketAddr,
192        request: &mut RemotingCommand,
193    ) -> Result<(), rocketmq_error::SharedError> {
194        for hook in &self.hooks {
195            hook.do_before_request(remote_addr, request)?;
196        }
197        Ok(())
198    }
199
200    fn do_after_response(
201        &self,
202        remote_addr: SocketAddr,
203        request: &RemotingCommand,
204        response: &mut RemotingCommand,
205    ) -> Result<(), rocketmq_error::SharedError> {
206        for hook in &self.hooks {
207            hook.do_after_response(remote_addr, request, response)?;
208        }
209        Ok(())
210    }
211}
212
213impl ProducerConfig {
214    fn compression_type_from_env() -> CompressionType {
215        match std::env::var(MESSAGE_COMPRESS_TYPE) {
216            Ok(compression_type) => Self::parse_compression_type_or_zlib(compression_type.as_str()),
217            Err(_) => CompressionType::Zlib,
218        }
219    }
220
221    fn parse_compression_type_or_zlib(compression_type: &str) -> CompressionType {
222        match CompressionType::try_of(compression_type) {
223            Ok(compression_type) => compression_type,
224            Err(error) => {
225                tracing::warn!(
226                    compression_type,
227                    error = %error,
228                    "invalid producer compression type, falling back to ZLIB"
229                );
230                CompressionType::Zlib
231            }
232        }
233    }
234
235    pub fn retry_response_codes(&self) -> &HashSet<i32> {
236        &self.retry_response_codes
237    }
238
239    pub fn producer_group(&self) -> &CheetahString {
240        &self.producer_group
241    }
242
243    pub fn topics(&self) -> &Vec<CheetahString> {
244        &self.topics
245    }
246
247    pub fn create_topic_key(&self) -> &CheetahString {
248        &self.create_topic_key
249    }
250    #[inline]
251    pub fn default_topic_queue_nums(&self) -> u32 {
252        self.default_topic_queue_nums
253    }
254
255    pub fn send_msg_timeout(&self) -> u32 {
256        self.send_msg_timeout
257    }
258
259    pub fn send_msg_max_timeout_per_request(&self) -> Option<u32> {
260        self.send_msg_max_timeout_per_request
261    }
262
263    pub fn compress_msg_body_over_howmuch(&self) -> u32 {
264        self.compress_msg_body_over_howmuch
265    }
266
267    pub fn retry_times_when_send_failed(&self) -> u32 {
268        self.retry_times_when_send_failed
269    }
270
271    pub fn retry_times_when_send_async_failed(&self) -> u32 {
272        self.retry_times_when_send_async_failed
273    }
274
275    #[inline]
276    pub fn retry_another_broker_when_not_store_ok(&self) -> bool {
277        self.retry_another_broker_when_not_store_ok
278    }
279
280    pub fn max_message_size(&self) -> u32 {
281        self.max_message_size
282    }
283
284    pub fn trace_dispatcher(&self) -> Option<&ArcTraceDispatcher> {
285        self.trace_dispatcher.as_ref()
286    }
287
288    pub fn auto_batch(&self) -> bool {
289        self.auto_batch
290    }
291
292    pub fn batch_max_delay_ms(&self) -> Option<u32> {
293        self.batch_max_delay_ms
294    }
295
296    pub fn batch_max_bytes(&self) -> Option<u64> {
297        self.batch_max_bytes
298    }
299
300    pub fn total_batch_max_bytes(&self) -> Option<u64> {
301        self.total_batch_max_bytes
302    }
303
304    pub fn produce_accumulator(&self) -> Option<&Arc<ProduceAccumulator>> {
305        self.produce_accumulator.as_ref()
306    }
307
308    pub fn enable_backpressure_for_async_mode(&self) -> bool {
309        self.enable_backpressure_for_async_mode
310    }
311
312    pub(crate) fn set_enable_backpressure_for_async_mode(&mut self, enable_backpressure_for_async_mode: bool) {
313        self.enable_backpressure_for_async_mode = enable_backpressure_for_async_mode;
314    }
315
316    pub fn back_pressure_for_async_send_num(&self) -> u32 {
317        self.back_pressure_for_async_send_num
318    }
319
320    pub(crate) fn set_back_pressure_for_async_send_num(&mut self, back_pressure_for_async_send_num: u32) {
321        self.back_pressure_for_async_send_num =
322            back_pressure_for_async_send_num.max(MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM);
323    }
324
325    pub fn back_pressure_for_async_send_size(&self) -> u32 {
326        self.back_pressure_for_async_send_size
327    }
328
329    pub(crate) fn set_back_pressure_for_async_send_size(&mut self, back_pressure_for_async_send_size: u32) {
330        self.back_pressure_for_async_send_size =
331            back_pressure_for_async_send_size.max(MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE);
332    }
333
334    pub fn rpc_hook(&self) -> &Option<Arc<dyn RPCHook>> {
335        &self.rpc_hook
336    }
337
338    pub fn compress_level(&self) -> i32 {
339        self.compress_level
340    }
341
342    pub fn compress_type(&self) -> CompressionType {
343        self.compress_type
344    }
345
346    pub fn compressor(&self) -> Option<&'static (dyn Compressor + Send + Sync)> {
347        self.compressor
348    }
349
350    pub(crate) fn latency_max(&self) -> &[u64] {
351        &self.latency_max
352    }
353
354    pub(crate) fn set_latency_max(&mut self, latency_max: Vec<u64>) {
355        self.latency_max = latency_max;
356    }
357
358    pub(crate) fn not_available_duration(&self) -> &[u64] {
359        &self.not_available_duration
360    }
361
362    pub(crate) fn set_not_available_duration(&mut self, not_available_duration: Vec<u64>) {
363        self.not_available_duration = not_available_duration;
364    }
365}
366
367impl Default for ProducerConfig {
368    fn default() -> Self {
369        let mut retry_response_codes = HashSet::new();
370        retry_response_codes.extend(vec![
371            ResponseCode::TopicNotExist as i32,
372            ResponseCode::ServiceNotAvailable as i32,
373            ResponseCode::SystemError as i32,
374            ResponseCode::SystemBusy as i32,
375            ResponseCode::NoPermission as i32,
376            ResponseCode::NoBuyerId as i32,
377            ResponseCode::NotInCurrentUnit as i32,
378        ]);
379        let compression_type = Self::compression_type_from_env();
380        Self {
381            retry_response_codes,
382            producer_group: CheetahString::empty(),
383            topics: vec![],
384            create_topic_key: CheetahString::from_static_str(TopicValidator::AUTO_CREATE_TOPIC_KEY_TOPIC),
385            default_topic_queue_nums: 4,
386            send_msg_timeout: 3000,
387            send_msg_max_timeout_per_request: None,
388            compress_msg_body_over_howmuch: 1024 * 4,
389            retry_times_when_send_failed: 2,
390            retry_times_when_send_async_failed: 2,
391            retry_another_broker_when_not_store_ok: false,
392            max_message_size: 1024 * 1024 * 4,
393            trace_dispatcher: None,
394            auto_batch: false,
395            batch_max_delay_ms: None,
396            batch_max_bytes: None,
397            total_batch_max_bytes: None,
398            produce_accumulator: None,
399            enable_backpressure_for_async_mode: false,
400            back_pressure_for_async_send_num: 1024,
401            back_pressure_for_async_send_size: 100 * 1024 * 1024,
402            rpc_hook: None,
403            compress_level: std::env::var(MESSAGE_COMPRESS_LEVEL)
404                .ok()
405                .and_then(|level| level.parse().ok())
406                .unwrap_or(5),
407            compress_type: compression_type,
408            compressor: Some(CompressorFactory::get_compressor(compression_type)),
409            latency_max: MQFaultStrategy::DEFAULT_LATENCY_MAX.to_vec(),
410            not_available_duration: MQFaultStrategy::DEFAULT_NOT_AVAILABLE_DURATION.to_vec(),
411        }
412    }
413}
414
415#[derive(Clone)]
416pub struct DefaultMQProducer {
417    session: Option<ClientSession>,
418    client_config: StableConfig<ClientConfig>,
419    producer_config: StableConfig<ProducerConfig>,
420    pub(crate) default_mqproducer_impl: Option<Arc<DefaultMQProducerImpl>>,
421}
422
423impl DefaultMQProducer {
424    pub(crate) fn unbound() -> Self {
425        Self {
426            session: None,
427            client_config: StableConfig::default(),
428            producer_config: StableConfig::default(),
429            default_mqproducer_impl: None,
430        }
431    }
432}
433
434impl ClientSessionProvider for DefaultMQProducer {
435    fn client_session(&self) -> Option<&ClientSession> {
436        self.session.as_ref()
437    }
438}
439
440impl DefaultMQProducer {
441    #[inline]
442    pub fn builder(client_runtime: Arc<ClientRuntime>) -> DefaultMQProducerBuilder {
443        DefaultMQProducerBuilder::new(client_runtime)
444    }
445    pub fn new(client_runtime: Arc<ClientRuntime>) -> Self {
446        Self::builder(client_runtime).build()
447    }
448
449    /// Returns the shared session for a producer created through the public
450    /// builder. Internal bootstrap producers intentionally have no public
451    /// session.
452    #[must_use]
453    pub fn client_session(&self) -> Option<&ClientSession> {
454        self.session.as_ref()
455    }
456
457    pub(crate) fn set_client_session(&mut self, session: ClientSession) {
458        self.session = Some(session);
459    }
460
461    pub async fn start(&mut self) -> crate::ClientResult<()> {
462        <Self as ProducerBackend>::start(self).await
463    }
464
465    pub async fn shutdown(&mut self) {
466        <Self as ProducerBackend>::shutdown(self).await;
467    }
468
469    /// Stops producer-owned work without shutting down the shared Client factory.
470    #[doc(hidden)]
471    pub async fn shutdown_for_shared_factory(&mut self) {
472        if let Some(producer) = self.default_mqproducer_impl.as_ref() {
473            if let Err(error) = producer.shutdown_after_partial_start_with_factory(false).await {
474                error!(?error, "DefaultMQProducerImpl shared-factory shutdown failed");
475            }
476        }
477    }
478
479    pub async fn fetch_publish_message_queues(&mut self, topic: &str) -> crate::ClientResult<Vec<MessageQueue>> {
480        <Self as ProducerBackend>::fetch_publish_message_queues(self, topic).await
481    }
482
483    pub async fn create_topic(
484        &mut self,
485        key: &str,
486        new_topic: &str,
487        queue_num: i32,
488        attributes: HashMap<String, String>,
489    ) -> crate::ClientResult<()> {
490        <Self as ProducerBackend>::create_topic(self, key, new_topic, queue_num, attributes).await
491    }
492
493    pub async fn create_topic_with_flag(
494        &mut self,
495        key: &str,
496        new_topic: &str,
497        queue_num: i32,
498        topic_sys_flag: i32,
499        attributes: HashMap<String, String>,
500    ) -> crate::ClientResult<()> {
501        <Self as ProducerBackend>::create_topic_with_flag(self, key, new_topic, queue_num, topic_sys_flag, attributes)
502            .await
503    }
504
505    pub async fn search_offset(&mut self, mq: &MessageQueue, timestamp: u64) -> crate::ClientResult<i64> {
506        <Self as ProducerBackend>::search_offset(self, mq, timestamp).await
507    }
508
509    pub async fn max_offset(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
510        <Self as ProducerBackend>::max_offset(self, mq).await
511    }
512
513    pub async fn min_offset(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
514        <Self as ProducerBackend>::min_offset(self, mq).await
515    }
516
517    pub async fn earliest_msg_store_time(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
518        <Self as ProducerBackend>::earliest_msg_store_time(self, mq).await
519    }
520
521    pub async fn query_message(
522        &mut self,
523        topic: &str,
524        key: &str,
525        max_num: i32,
526        begin: u64,
527        end: u64,
528    ) -> crate::ClientResult<QueryResult> {
529        <Self as ProducerBackend>::query_message(self, topic, key, max_num, begin, end).await
530    }
531
532    pub async fn view_message(&mut self, topic: &str, msg_id: &str) -> crate::ClientResult<MessageExt> {
533        <Self as ProducerBackend>::view_message(self, topic, msg_id).await
534    }
535
536    pub async fn send<M>(&self, msg: M) -> crate::ClientResult<Option<SendResult>>
537    where
538        M: MessageTrait + Send + Sync,
539    {
540        <Self as ProducerBackend>::send(self, msg).await
541    }
542
543    pub async fn send_with_timeout<M>(&self, msg: M, timeout: u64) -> crate::ClientResult<Option<SendResult>>
544    where
545        M: MessageTrait + Send + Sync,
546    {
547        <Self as ProducerBackend>::send_with_timeout(self, msg, timeout).await
548    }
549
550    pub async fn send_with_callback<M, F>(&self, msg: M, send_callback: F) -> crate::ClientResult<()>
551    where
552        M: MessageTrait + Send + Sync,
553        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
554    {
555        <Self as ProducerBackend>::send_with_callback(self, msg, send_callback).await
556    }
557
558    pub async fn send_with_callback_timeout<F, M>(
559        &self,
560        msg: M,
561        send_callback: F,
562        timeout: u64,
563    ) -> crate::ClientResult<()>
564    where
565        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
566        M: MessageTrait + Send + Sync,
567    {
568        <Self as ProducerBackend>::send_with_callback_timeout(self, msg, send_callback, timeout).await
569    }
570
571    pub async fn send_oneway<M>(&self, msg: M) -> crate::ClientResult<()>
572    where
573        M: MessageTrait + Send + Sync,
574    {
575        <Self as ProducerBackend>::send_oneway(self, msg).await
576    }
577
578    pub async fn send_to_queue<M>(&self, msg: M, mq: MessageQueue) -> crate::ClientResult<Option<SendResult>>
579    where
580        M: MessageTrait + Send + Sync,
581    {
582        <Self as ProducerBackend>::send_to_queue(self, msg, mq).await
583    }
584
585    pub async fn send_to_queue_with_timeout<M>(
586        &self,
587        msg: M,
588        mq: MessageQueue,
589        timeout: u64,
590    ) -> crate::ClientResult<Option<SendResult>>
591    where
592        M: MessageTrait + Send + Sync,
593    {
594        <Self as ProducerBackend>::send_to_queue_with_timeout(self, msg, mq, timeout).await
595    }
596
597    pub async fn send_to_queue_with_callback<M, F>(
598        &self,
599        msg: M,
600        mq: MessageQueue,
601        send_callback: F,
602    ) -> crate::ClientResult<()>
603    where
604        M: MessageTrait + Send + Sync,
605        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
606    {
607        <Self as ProducerBackend>::send_to_queue_with_callback(self, msg, mq, send_callback).await
608    }
609
610    pub async fn send_to_queue_with_callback_timeout<M, F>(
611        &self,
612        msg: M,
613        mq: MessageQueue,
614        send_callback: F,
615        timeout: u64,
616    ) -> crate::ClientResult<()>
617    where
618        M: MessageTrait + Send + Sync,
619        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
620    {
621        <Self as ProducerBackend>::send_to_queue_with_callback_timeout(self, msg, mq, send_callback, timeout).await
622    }
623
624    pub async fn send_oneway_to_queue<M>(&self, msg: M, mq: MessageQueue) -> crate::ClientResult<()>
625    where
626        M: MessageTrait + Send + Sync,
627    {
628        <Self as ProducerBackend>::send_oneway_to_queue(self, msg, mq).await
629    }
630
631    pub async fn send_with_selector<M, S, T>(
632        &self,
633        msg: M,
634        selector: S,
635        arg: T,
636    ) -> crate::ClientResult<Option<SendResult>>
637    where
638        M: MessageTrait + Send + Sync,
639        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
640        T: Send + Sync,
641    {
642        <Self as ProducerBackend>::send_with_selector(self, msg, selector, arg).await
643    }
644
645    pub async fn send_with_selector_timeout<M, S, T>(
646        &self,
647        msg: M,
648        selector: S,
649        arg: T,
650        timeout: u64,
651    ) -> crate::ClientResult<Option<SendResult>>
652    where
653        M: MessageTrait + Send + Sync,
654        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
655        T: Send + Sync,
656    {
657        <Self as ProducerBackend>::send_with_selector_timeout(self, msg, selector, arg, timeout).await
658    }
659
660    pub async fn send_with_selector_callback<M, S, T>(
661        &self,
662        msg: M,
663        selector: S,
664        arg: T,
665        send_callback: Option<ArcSendCallback>,
666    ) -> crate::ClientResult<()>
667    where
668        M: MessageTrait + Send + Sync,
669        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
670        T: Send + Sync,
671    {
672        <Self as ProducerBackend>::send_with_selector_callback(self, msg, selector, arg, send_callback).await
673    }
674
675    pub async fn send_with_selector_callback_timeout<M, S, T>(
676        &self,
677        msg: M,
678        selector: S,
679        arg: T,
680        send_callback: Option<ArcSendCallback>,
681        timeout: u64,
682    ) -> crate::ClientResult<()>
683    where
684        M: MessageTrait + Send + Sync,
685        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
686        T: Send + Sync + 'static,
687    {
688        <Self as ProducerBackend>::send_with_selector_callback_timeout(self, msg, selector, arg, send_callback, timeout)
689            .await
690    }
691
692    pub async fn send_oneway_with_selector<M, S, T>(&self, msg: M, selector: S, arg: T) -> crate::ClientResult<()>
693    where
694        M: MessageTrait + Send + Sync,
695        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
696        T: Send + Sync + 'static,
697    {
698        <Self as ProducerBackend>::send_oneway_with_selector(self, msg, selector, arg).await
699    }
700
701    pub async fn send_message_in_transaction<T, M>(
702        &self,
703        msg: M,
704        arg: Option<T>,
705    ) -> crate::ClientResult<TransactionSendResult>
706    where
707        T: std::any::Any + Sync + Send,
708        M: MessageTrait + Send + Sync,
709    {
710        <Self as ProducerBackend>::send_message_in_transaction(self, msg, arg).await
711    }
712
713    pub async fn send_batch<M>(&self, msgs: Vec<M>) -> crate::ClientResult<SendResult>
714    where
715        M: MessageTrait + Send + Sync,
716    {
717        <Self as ProducerBackend>::send_batch(self, msgs).await
718    }
719
720    pub async fn send_batch_with_timeout<M>(&self, msgs: Vec<M>, timeout: u64) -> crate::ClientResult<SendResult>
721    where
722        M: MessageTrait + Send + Sync,
723    {
724        <Self as ProducerBackend>::send_batch_with_timeout(self, msgs, timeout).await
725    }
726
727    pub async fn send_batch_to_queue<M>(&self, msgs: Vec<M>, mq: MessageQueue) -> crate::ClientResult<SendResult>
728    where
729        M: MessageTrait + Send + Sync,
730    {
731        <Self as ProducerBackend>::send_batch_to_queue(self, msgs, mq).await
732    }
733
734    pub async fn send_batch_to_queue_with_timeout<M>(
735        &self,
736        msgs: Vec<M>,
737        mq: MessageQueue,
738        timeout: u64,
739    ) -> crate::ClientResult<SendResult>
740    where
741        M: MessageTrait + Send + Sync,
742    {
743        <Self as ProducerBackend>::send_batch_to_queue_with_timeout(self, msgs, mq, timeout).await
744    }
745
746    pub async fn send_batch_with_callback<M, F>(&self, msgs: Vec<M>, f: F) -> crate::ClientResult<()>
747    where
748        M: MessageTrait + Send + Sync,
749        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
750    {
751        <Self as ProducerBackend>::send_batch_with_callback(self, msgs, f).await
752    }
753
754    pub async fn send_batch_with_callback_timeout<M, F>(
755        &self,
756        msgs: Vec<M>,
757        f: F,
758        timeout: u64,
759    ) -> crate::ClientResult<()>
760    where
761        M: MessageTrait + Send + Sync,
762        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
763    {
764        <Self as ProducerBackend>::send_batch_with_callback_timeout(self, msgs, f, timeout).await
765    }
766
767    pub async fn send_batch_to_queue_with_callback<M, F>(
768        &self,
769        msgs: Vec<M>,
770        mq: MessageQueue,
771        f: F,
772    ) -> crate::ClientResult<()>
773    where
774        M: MessageTrait + Send + Sync,
775        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
776    {
777        <Self as ProducerBackend>::send_batch_to_queue_with_callback(self, msgs, mq, f).await
778    }
779
780    pub async fn send_batch_to_queue_with_callback_timeout<M, F>(
781        &self,
782        msgs: Vec<M>,
783        mq: MessageQueue,
784        f: F,
785        timeout: u64,
786    ) -> crate::ClientResult<()>
787    where
788        M: MessageTrait + Send + Sync,
789        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
790    {
791        <Self as ProducerBackend>::send_batch_to_queue_with_callback_timeout(self, msgs, mq, f, timeout).await
792    }
793
794    pub async fn request<M>(&self, msg: M, timeout: u64) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
795    where
796        M: MessageTrait + Send + Sync,
797    {
798        <Self as ProducerBackend>::request(self, msg, timeout).await
799    }
800
801    pub async fn request_with_callback<F, M>(
802        &self,
803        msg: M,
804        request_callback: F,
805        timeout: u64,
806    ) -> crate::ClientResult<()>
807    where
808        F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
809        M: MessageTrait + Send + Sync,
810    {
811        <Self as ProducerBackend>::request_with_callback(self, msg, request_callback, timeout).await
812    }
813
814    pub async fn request_with_selector<M, S, T>(
815        &self,
816        msg: M,
817        selector: S,
818        arg: T,
819        timeout: u64,
820    ) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
821    where
822        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
823        T: Send + Sync + 'static,
824        M: MessageTrait + Send + Sync,
825    {
826        <Self as ProducerBackend>::request_with_selector(self, msg, selector, arg, timeout).await
827    }
828
829    pub async fn request_with_selector_callback<M, S, T, F>(
830        &self,
831        msg: M,
832        selector: S,
833        arg: T,
834        request_callback: F,
835        timeout: u64,
836    ) -> crate::ClientResult<()>
837    where
838        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
839        F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
840        T: Send + Sync + 'static,
841        M: MessageTrait + Send + Sync,
842    {
843        <Self as ProducerBackend>::request_with_selector_callback(self, msg, selector, arg, request_callback, timeout)
844            .await
845    }
846
847    pub async fn request_to_queue<M>(
848        &self,
849        msg: M,
850        mq: MessageQueue,
851        timeout: u64,
852    ) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
853    where
854        M: MessageTrait + Send + Sync,
855    {
856        <Self as ProducerBackend>::request_to_queue(self, msg, mq, timeout).await
857    }
858
859    pub async fn request_to_queue_with_callback<M, F>(
860        &self,
861        msg: M,
862        mq: MessageQueue,
863        request_callback: F,
864        timeout: u64,
865    ) -> crate::ClientResult<()>
866    where
867        F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
868        M: MessageTrait + Send + Sync,
869    {
870        <Self as ProducerBackend>::request_to_queue_with_callback(self, msg, mq, request_callback, timeout).await
871    }
872
873    pub async fn recall_message(
874        &self,
875        topic: impl Into<CheetahString>,
876        recall_handle: impl Into<CheetahString>,
877    ) -> crate::ClientResult<String> {
878        <Self as ProducerBackend>::recall_message(self, topic, recall_handle).await
879    }
880
881    #[inline]
882    pub fn client_config_snapshot(&self) -> Arc<ClientConfig> {
883        self.client_config.snapshot()
884    }
885
886    #[inline]
887    pub fn default_mq_producer_impl(&self) -> Option<&Arc<DefaultMQProducerImpl>> {
888        self.default_mqproducer_impl.as_ref()
889    }
890
891    #[inline]
892    pub fn get_default_mq_producer_impl(&self) -> Option<&Arc<DefaultMQProducerImpl>> {
893        self.default_mq_producer_impl()
894    }
895
896    #[inline]
897    pub fn retry_response_codes(&self) -> HashSet<i32> {
898        self.producer_config.snapshot().retry_response_codes.clone()
899    }
900
901    #[inline]
902    pub fn get_retry_response_codes(&self) -> HashSet<i32> {
903        self.retry_response_codes()
904    }
905
906    #[inline]
907    pub fn producer_group(&self) -> CheetahString {
908        self.producer_config.snapshot().producer_group.clone()
909    }
910
911    #[inline]
912    pub fn get_producer_group(&self) -> CheetahString {
913        self.producer_group()
914    }
915
916    #[inline]
917    pub fn topics(&self) -> Vec<CheetahString> {
918        self.producer_config.snapshot().topics.clone()
919    }
920
921    #[inline]
922    pub fn get_topics(&self) -> Vec<CheetahString> {
923        self.topics()
924    }
925
926    #[inline]
927    pub fn create_topic_key(&self) -> CheetahString {
928        self.producer_config.snapshot().create_topic_key.clone()
929    }
930
931    #[inline]
932    pub fn get_create_topic_key(&self) -> CheetahString {
933        self.create_topic_key()
934    }
935
936    #[inline]
937    pub fn default_topic_queue_nums(&self) -> u32 {
938        self.producer_config.snapshot().default_topic_queue_nums
939    }
940
941    #[inline]
942    pub fn get_default_topic_queue_nums(&self) -> u32 {
943        self.default_topic_queue_nums()
944    }
945
946    #[inline]
947    pub fn send_msg_timeout(&self) -> u32 {
948        self.producer_config.snapshot().send_msg_timeout
949    }
950
951    #[inline]
952    pub fn get_send_msg_timeout(&self) -> u32 {
953        self.send_msg_timeout()
954    }
955
956    #[inline]
957    pub fn compress_msg_body_over_howmuch(&self) -> u32 {
958        self.producer_config.snapshot().compress_msg_body_over_howmuch
959    }
960
961    #[inline]
962    pub fn get_compress_msg_body_over_howmuch(&self) -> u32 {
963        self.compress_msg_body_over_howmuch()
964    }
965
966    #[inline]
967    pub fn retry_times_when_send_failed(&self) -> u32 {
968        self.producer_config.snapshot().retry_times_when_send_failed
969    }
970
971    #[inline]
972    pub fn get_retry_times_when_send_failed(&self) -> u32 {
973        self.retry_times_when_send_failed()
974    }
975
976    #[inline]
977    pub fn retry_times_when_send_async_failed(&self) -> u32 {
978        self.producer_config.snapshot().retry_times_when_send_async_failed
979    }
980
981    #[inline]
982    pub fn get_retry_times_when_send_async_failed(&self) -> u32 {
983        self.retry_times_when_send_async_failed()
984    }
985
986    #[inline]
987    pub fn retry_another_broker_when_not_store_ok(&self) -> bool {
988        self.producer_config.snapshot().retry_another_broker_when_not_store_ok
989    }
990
991    #[inline]
992    pub fn is_retry_another_broker_when_not_store_ok(&self) -> bool {
993        self.retry_another_broker_when_not_store_ok()
994    }
995
996    #[inline]
997    pub fn is_send_message_with_vip_channel(&self) -> bool {
998        self.client_config.snapshot().is_vip_channel_enabled()
999    }
1000
1001    #[inline]
1002    pub fn is_send_message_with_vipchannel(&self) -> bool {
1003        self.is_send_message_with_vip_channel()
1004    }
1005
1006    #[inline]
1007    pub fn max_message_size(&self) -> u32 {
1008        self.producer_config.snapshot().max_message_size
1009    }
1010
1011    #[inline]
1012    pub fn get_max_message_size(&self) -> u32 {
1013        self.max_message_size()
1014    }
1015
1016    #[inline]
1017    pub fn trace_dispatcher(&self) -> Option<ArcTraceDispatcher> {
1018        self.producer_config.snapshot().trace_dispatcher.clone()
1019    }
1020
1021    #[inline]
1022    pub fn get_trace_dispatcher(&self) -> Option<ArcTraceDispatcher> {
1023        self.trace_dispatcher()
1024    }
1025
1026    #[inline]
1027    pub fn auto_batch(&self) -> bool {
1028        self.producer_config.snapshot().auto_batch
1029    }
1030
1031    pub fn produce_accumulator(&self) -> Option<Arc<ProduceAccumulator>> {
1032        self.producer_config.snapshot().produce_accumulator.clone()
1033    }
1034
1035    pub fn enable_backpressure_for_async_mode(&self) -> bool {
1036        self.producer_config.snapshot().enable_backpressure_for_async_mode
1037    }
1038
1039    #[inline]
1040    pub fn is_enable_backpressure_for_async_mode(&self) -> bool {
1041        self.enable_backpressure_for_async_mode()
1042    }
1043
1044    pub fn back_pressure_for_async_send_num(&self) -> u32 {
1045        self.producer_config.snapshot().back_pressure_for_async_send_num
1046    }
1047
1048    #[inline]
1049    pub fn get_back_pressure_for_async_send_num(&self) -> u32 {
1050        self.back_pressure_for_async_send_num()
1051    }
1052
1053    pub fn back_pressure_for_async_send_size(&self) -> u32 {
1054        self.producer_config.snapshot().back_pressure_for_async_send_size
1055    }
1056
1057    #[inline]
1058    pub fn get_back_pressure_for_async_send_size(&self) -> u32 {
1059        self.back_pressure_for_async_send_size()
1060    }
1061
1062    #[inline]
1063    pub fn send_msg_max_timeout_per_request(&self) -> Option<u32> {
1064        self.producer_config.snapshot().send_msg_max_timeout_per_request
1065    }
1066
1067    #[inline]
1068    pub fn get_send_msg_max_timeout_per_request(&self) -> Option<u32> {
1069        self.send_msg_max_timeout_per_request()
1070    }
1071
1072    #[inline]
1073    pub fn batch_max_delay_ms(&self) -> Option<u32> {
1074        self.producer_config.snapshot().batch_max_delay_ms
1075    }
1076
1077    #[inline]
1078    pub fn get_batch_max_delay_ms(&self) -> Option<u32> {
1079        self.batch_max_delay_ms()
1080    }
1081
1082    #[inline]
1083    pub fn batch_max_bytes(&self) -> Option<u64> {
1084        self.producer_config.snapshot().batch_max_bytes
1085    }
1086
1087    #[inline]
1088    pub fn get_batch_max_bytes(&self) -> Option<u64> {
1089        self.batch_max_bytes()
1090    }
1091
1092    #[inline]
1093    pub fn total_batch_max_bytes(&self) -> Option<u64> {
1094        self.producer_config.snapshot().total_batch_max_bytes
1095    }
1096
1097    #[inline]
1098    pub fn get_total_batch_max_bytes(&self) -> Option<u64> {
1099        self.total_batch_max_bytes()
1100    }
1101
1102    pub fn rpc_hook(&self) -> Option<Arc<dyn RPCHook>> {
1103        self.producer_config.snapshot().rpc_hook.clone()
1104    }
1105
1106    pub fn compress_level(&self) -> i32 {
1107        self.producer_config.snapshot().compress_level
1108    }
1109
1110    #[inline]
1111    pub fn get_compress_level(&self) -> i32 {
1112        self.compress_level()
1113    }
1114
1115    pub fn compress_type(&self) -> CompressionType {
1116        self.producer_config.snapshot().compress_type
1117    }
1118
1119    pub fn get_compress_type(&self) -> CompressionType {
1120        self.compress_type()
1121    }
1122
1123    pub fn compressor(&self) -> Option<&'static (dyn Compressor + Send + Sync)> {
1124        self.producer_config.snapshot().compressor
1125    }
1126
1127    pub fn get_compressor(&self) -> Option<&'static (dyn Compressor + Send + Sync)> {
1128        self.compressor()
1129    }
1130
1131    #[inline]
1132    pub fn is_use_tls(&self) -> bool {
1133        self.client_config.snapshot().is_use_tls()
1134    }
1135
1136    pub fn set_use_tls(&mut self, use_tls: bool) {
1137        self.client_config.update(|config| config.set_use_tls(use_tls));
1138        if let Some(default_mqproducer_impl) = self.default_mqproducer_impl.as_ref() {
1139            default_mqproducer_impl.set_use_tls(use_tls);
1140        }
1141        let producer_config = self.producer_config.snapshot();
1142        if let Some(dispatcher) = producer_config.trace_dispatcher.as_ref() {
1143            if let Some(async_dispatcher) = dispatcher.as_any().downcast_ref::<AsyncTraceDispatcher>() {
1144                async_dispatcher.set_use_tls(use_tls);
1145            }
1146        }
1147    }
1148
1149    pub fn set_client_config(&mut self, client_config: ClientConfig) {
1150        self.client_config.replace(client_config);
1151        if let Some(default_mqproducer_impl) = self.default_mqproducer_impl.as_ref() {
1152            default_mqproducer_impl.set_use_tls(self.client_config.snapshot().use_tls);
1153        }
1154    }
1155
1156    pub(crate) fn set_default_mqproducer_impl(&mut self, default_mqproducer_impl: DefaultMQProducerImpl) {
1157        let wrapper = Arc::new(default_mqproducer_impl);
1158        // The root is freshly allocated and has not been published, so no competing
1159        // owner can initialize its self reference to a different allocation.
1160        wrapper
1161            .initialize_self_reference(&wrapper)
1162            .expect("fresh DefaultMQProducerImpl root must accept its own weak reference");
1163        self.client_config.replace(wrapper.client_config_snapshot());
1164        self.producer_config
1165            .replace(wrapper.producer_config_snapshot().as_ref().clone());
1166        self.default_mqproducer_impl = Some(wrapper);
1167    }
1168
1169    fn sync_producer_config_to_impl(&self) {
1170        if let Some(default_mqproducer_impl) = self.default_mqproducer_impl.as_ref() {
1171            default_mqproducer_impl.replace_producer_config(self.producer_config.snapshot().as_ref().clone());
1172        }
1173    }
1174
1175    fn update_producer_config(&self, update: impl FnOnce(&mut ProducerConfig)) {
1176        self.producer_config.update(update);
1177        self.sync_producer_config_to_impl();
1178    }
1179
1180    pub fn set_retry_response_codes(&mut self, retry_response_codes: HashSet<i32>) {
1181        self.update_producer_config(|config| config.retry_response_codes = retry_response_codes);
1182    }
1183
1184    pub fn add_retry_response_code(&mut self, response_code: i32) {
1185        self.update_producer_config(|config| {
1186            config.retry_response_codes.insert(response_code);
1187        });
1188    }
1189
1190    #[inline]
1191    pub fn set_producer_group(&mut self, producer_group: impl Into<CheetahString>) {
1192        let producer_group = producer_group.into();
1193        self.update_producer_config(|config| config.producer_group = producer_group);
1194    }
1195
1196    pub fn set_topics(&mut self, topics: Vec<CheetahString>) {
1197        self.update_producer_config(|config| config.topics = topics);
1198    }
1199
1200    pub fn set_create_topic_key(&mut self, create_topic_key: impl Into<CheetahString>) {
1201        let create_topic_key = create_topic_key.into();
1202        self.update_producer_config(|config| config.create_topic_key = create_topic_key);
1203    }
1204
1205    pub fn set_default_topic_queue_nums(&mut self, default_topic_queue_nums: u32) {
1206        self.update_producer_config(|config| config.default_topic_queue_nums = default_topic_queue_nums);
1207    }
1208
1209    pub fn set_send_msg_timeout(&mut self, send_msg_timeout: u32) {
1210        self.update_producer_config(|config| config.send_msg_timeout = send_msg_timeout);
1211    }
1212
1213    pub fn set_compress_msg_body_over_howmuch(&mut self, compress_msg_body_over_howmuch: u32) {
1214        self.update_producer_config(|config| {
1215            config.compress_msg_body_over_howmuch = compress_msg_body_over_howmuch;
1216        });
1217    }
1218
1219    pub fn set_retry_times_when_send_failed(&mut self, retry_times_when_send_failed: u32) {
1220        self.update_producer_config(|config| config.retry_times_when_send_failed = retry_times_when_send_failed);
1221    }
1222
1223    pub fn set_retry_times_when_send_async_failed(&mut self, retry_times_when_send_async_failed: u32) {
1224        self.update_producer_config(|config| {
1225            config.retry_times_when_send_async_failed = retry_times_when_send_async_failed;
1226        });
1227    }
1228
1229    pub fn set_retry_another_broker_when_not_store_ok(&mut self, retry_another_broker_when_not_store_ok: bool) {
1230        self.update_producer_config(|config| {
1231            config.retry_another_broker_when_not_store_ok = retry_another_broker_when_not_store_ok;
1232        });
1233    }
1234
1235    pub fn set_send_message_with_vip_channel(&mut self, send_message_with_vip_channel: bool) {
1236        self.client_config
1237            .update(|config| config.set_vip_channel_enabled(send_message_with_vip_channel));
1238        if let Some(default_mqproducer_impl) = self.default_mqproducer_impl.as_ref() {
1239            default_mqproducer_impl.set_send_message_with_vip_channel(send_message_with_vip_channel);
1240        }
1241    }
1242
1243    pub fn set_send_message_with_vipchannel(&mut self, send_message_with_vip_channel: bool) {
1244        self.set_send_message_with_vip_channel(send_message_with_vip_channel);
1245    }
1246
1247    pub fn set_max_message_size(&mut self, max_message_size: u32) {
1248        self.update_producer_config(|config| config.max_message_size = max_message_size);
1249    }
1250
1251    pub fn set_trace_dispatcher(&mut self, trace_dispatcher: ArcTraceDispatcher) {
1252        self.update_producer_config(|config| config.trace_dispatcher = Some(trace_dispatcher));
1253    }
1254
1255    pub fn set_auto_batch(&mut self, auto_batch: bool) {
1256        self.update_producer_config(|config| config.auto_batch = auto_batch);
1257    }
1258
1259    pub fn set_produce_accumulator(&mut self, produce_accumulator: ProduceAccumulator) {
1260        self.apply_batch_config_to_accumulator(&produce_accumulator);
1261        self.update_producer_config(|config| {
1262            config.produce_accumulator = Some(Arc::new(produce_accumulator));
1263        });
1264    }
1265
1266    pub fn set_enable_backpressure_for_async_mode(&mut self, enable_backpressure_for_async_mode: bool) {
1267        self.update_producer_config(|config| {
1268            config.set_enable_backpressure_for_async_mode(enable_backpressure_for_async_mode);
1269        });
1270    }
1271
1272    pub fn set_back_pressure_for_async_send_num(&mut self, back_pressure_for_async_send_num: u32) {
1273        self.update_producer_config(|config| {
1274            config.set_back_pressure_for_async_send_num(back_pressure_for_async_send_num);
1275        });
1276    }
1277
1278    pub fn set_back_pressure_for_async_send_size(&mut self, back_pressure_for_async_send_size: u32) {
1279        self.update_producer_config(|config| {
1280            config.set_back_pressure_for_async_send_size(back_pressure_for_async_send_size);
1281        });
1282    }
1283
1284    pub fn set_rpc_hook(&mut self, rpc_hook: Arc<dyn RPCHook>) {
1285        self.producer_config
1286            .update(|config| config.rpc_hook = Some(rpc_hook.clone()));
1287        if let Some(ref default_mqproducer_impl) = self.default_mqproducer_impl {
1288            default_mqproducer_impl.set_rpc_hook(rpc_hook);
1289        }
1290        self.sync_producer_config_to_impl();
1291    }
1292
1293    pub fn set_compress_level(&mut self, compress_level: i32) {
1294        self.update_producer_config(|config| config.compress_level = compress_level);
1295    }
1296
1297    pub fn set_compress_type(&mut self, compress_type: CompressionType) {
1298        self.update_producer_config(|config| {
1299            config.compress_type = compress_type;
1300            config.compressor = Some(CompressorFactory::get_compressor(compress_type));
1301        });
1302    }
1303
1304    pub fn set_compressor(&mut self, compressor: Option<&'static (dyn Compressor + Send + Sync)>) {
1305        self.update_producer_config(|config| config.compressor = compressor);
1306    }
1307
1308    #[inline]
1309    pub fn set_send_msg_max_timeout_per_request(&mut self, timeout: u32) {
1310        self.update_producer_config(|config| config.send_msg_max_timeout_per_request = Some(timeout));
1311    }
1312
1313    #[inline]
1314    pub fn set_send_msg_max_timeout_per_request_option(&mut self, timeout: Option<u32>) {
1315        self.update_producer_config(|config| config.send_msg_max_timeout_per_request = timeout);
1316    }
1317
1318    #[inline]
1319    pub fn set_batch_max_delay_ms(&mut self, delay_ms: u32) {
1320        self.producer_config
1321            .update(|config| config.batch_max_delay_ms = Some(delay_ms));
1322        let producer_config = self.producer_config.snapshot();
1323        if let Some(produce_accumulator) = producer_config.produce_accumulator.as_ref() {
1324            if let Err(error) = produce_accumulator.set_batch_max_delay_ms(delay_ms) {
1325                tracing::warn!("ignore invalid batchMaxDelayMs for ProduceAccumulator: {error}");
1326            }
1327        }
1328        self.sync_producer_config_to_impl();
1329    }
1330
1331    #[inline]
1332    pub fn set_batch_max_delay_ms_option(&mut self, delay_ms: Option<u32>) {
1333        self.update_producer_config(|config| config.batch_max_delay_ms = delay_ms);
1334    }
1335
1336    #[inline]
1337    pub fn set_batch_max_bytes(&mut self, bytes: u64) {
1338        self.producer_config
1339            .update(|config| config.batch_max_bytes = Some(bytes));
1340        let producer_config = self.producer_config.snapshot();
1341        if let Some(produce_accumulator) = producer_config.produce_accumulator.as_ref() {
1342            if let Err(error) = produce_accumulator.set_batch_max_bytes(bytes) {
1343                tracing::warn!("ignore invalid batchMaxBytes for ProduceAccumulator: {error}");
1344            }
1345        }
1346        self.sync_producer_config_to_impl();
1347    }
1348
1349    #[inline]
1350    pub fn set_batch_max_bytes_option(&mut self, bytes: Option<u64>) {
1351        self.update_producer_config(|config| config.batch_max_bytes = bytes);
1352    }
1353
1354    #[inline]
1355    pub fn set_total_batch_max_bytes(&mut self, bytes: u64) {
1356        self.producer_config
1357            .update(|config| config.total_batch_max_bytes = Some(bytes));
1358        let producer_config = self.producer_config.snapshot();
1359        if let Some(produce_accumulator) = producer_config.produce_accumulator.as_ref() {
1360            if let Err(error) = produce_accumulator.set_total_batch_max_bytes(bytes) {
1361                tracing::warn!("ignore invalid totalBatchMaxBytes for ProduceAccumulator: {error}");
1362            }
1363        }
1364        self.sync_producer_config_to_impl();
1365    }
1366
1367    #[inline]
1368    pub fn set_total_batch_max_bytes_option(&mut self, bytes: Option<u64>) {
1369        self.update_producer_config(|config| config.total_batch_max_bytes = bytes);
1370    }
1371
1372    /// Returns the current immutable producer configuration snapshot.
1373    pub fn producer_config_snapshot(&self) -> Arc<ProducerConfig> {
1374        self.producer_config.snapshot()
1375    }
1376
1377    fn apply_batch_config_to_accumulator(&self, produce_accumulator: &ProduceAccumulator) {
1378        let producer_config = self.producer_config.snapshot();
1379        if let Some(delay_ms) = producer_config.batch_max_delay_ms {
1380            if let Err(error) = produce_accumulator.set_batch_max_delay_ms(delay_ms) {
1381                tracing::warn!("ignore invalid batchMaxDelayMs for ProduceAccumulator: {error}");
1382            }
1383        }
1384        if let Some(bytes) = producer_config.batch_max_bytes {
1385            if let Err(error) = produce_accumulator.set_batch_max_bytes(bytes) {
1386                tracing::warn!("ignore invalid batchMaxBytes for ProduceAccumulator: {error}");
1387            }
1388        }
1389        if let Some(bytes) = producer_config.total_batch_max_bytes {
1390            if let Err(error) = produce_accumulator.set_total_batch_max_bytes(bytes) {
1391                tracing::warn!("ignore invalid totalBatchMaxBytes for ProduceAccumulator: {error}");
1392            }
1393        }
1394    }
1395
1396    #[inline]
1397    pub fn set_send_latency_fault_enable(&mut self, send_latency_fault_enable: bool) {
1398        self.client_config
1399            .update(|config| config.set_send_latency_enable(send_latency_fault_enable));
1400        if let Some(ref default_mqproducer_impl) = self.default_mqproducer_impl {
1401            default_mqproducer_impl.set_send_latency_fault_enable(send_latency_fault_enable);
1402        }
1403    }
1404
1405    #[inline]
1406    pub fn is_send_latency_fault_enable(&self) -> bool {
1407        self.default_mqproducer_impl
1408            .as_ref()
1409            .map(|producer_impl| producer_impl.is_send_latency_fault_enable())
1410            .unwrap_or_else(|| self.client_config.snapshot().is_send_latency_enable())
1411    }
1412
1413    #[inline]
1414    pub fn set_start_detector_enable(&mut self, start_detector_enable: bool) {
1415        self.client_config
1416            .update(|config| config.set_start_detector_enable(start_detector_enable));
1417        if let Some(ref default_mqproducer_impl) = self.default_mqproducer_impl {
1418            default_mqproducer_impl.set_start_detector_enable(start_detector_enable);
1419        }
1420    }
1421
1422    #[inline]
1423    pub fn is_start_detector_enable(&self) -> bool {
1424        self.default_mqproducer_impl
1425            .as_ref()
1426            .map(|producer_impl| producer_impl.is_start_detector_enable())
1427            .unwrap_or_else(|| self.client_config.snapshot().is_start_detector_enable())
1428    }
1429
1430    pub fn latency_max(&self) -> Vec<u64> {
1431        self.producer_config.snapshot().latency_max.clone()
1432    }
1433
1434    pub fn get_latency_max(&self) -> Vec<u64> {
1435        self.latency_max()
1436    }
1437
1438    pub fn set_latency_max(&mut self, latency_max: impl Into<Vec<u64>>) {
1439        let latency_max = latency_max.into();
1440        self.producer_config
1441            .update(|config| config.latency_max = latency_max.clone());
1442        if let Some(default_mqproducer_impl) = self.default_mqproducer_impl.as_ref() {
1443            default_mqproducer_impl.set_latency_max(latency_max);
1444        }
1445    }
1446
1447    pub fn not_available_duration(&self) -> Vec<u64> {
1448        self.producer_config.snapshot().not_available_duration.clone()
1449    }
1450
1451    pub fn get_not_available_duration(&self) -> Vec<u64> {
1452        self.not_available_duration()
1453    }
1454
1455    pub fn set_not_available_duration(&mut self, not_available_duration: impl Into<Vec<u64>>) {
1456        let not_available_duration = not_available_duration.into();
1457        self.producer_config
1458            .update(|config| config.not_available_duration = not_available_duration.clone());
1459        if let Some(default_mqproducer_impl) = self.default_mqproducer_impl.as_ref() {
1460            default_mqproducer_impl.set_not_available_duration(not_available_duration);
1461        }
1462    }
1463
1464    pub fn init_produce_accumulator(&mut self) {
1465        let Some(producer_impl) = self.default_mqproducer_impl.as_ref() else {
1466            error!("cannot initialize produce accumulator without a ClientRuntime-bound producer");
1467            return;
1468        };
1469        let Some(produce_accumulator) = producer_impl
1470            .client_pool()
1471            .get_or_create_produce_accumulator(self.client_config.snapshot().as_ref().clone())
1472        else {
1473            error!("cannot initialize produce accumulator after ClientRuntime shutdown");
1474            return;
1475        };
1476        self.apply_batch_config_to_accumulator(&produce_accumulator);
1477        self.update_producer_config(|config| config.produce_accumulator = Some(produce_accumulator));
1478    }
1479
1480    pub fn set_back_pressure_for_async_send_num_inside_adjust(&mut self, back_pressure_for_async_send_num: u32) {
1481        self.set_back_pressure_for_async_send_num(back_pressure_for_async_send_num);
1482    }
1483
1484    pub fn set_back_pressure_for_async_send_size_inside_adjust(&mut self, back_pressure_for_async_send_size: u32) {
1485        self.set_back_pressure_for_async_send_size(back_pressure_for_async_send_size);
1486    }
1487
1488    fn batch<M>(&self, messages: Vec<M>) -> crate::ClientResult<MessageBatch>
1489    where
1490        M: MessageTrait + Send + Sync,
1491    {
1492        let mut msg_batch = match MessageBatch::generate_from_vec(messages) {
1493            Ok(msg_batch) => msg_batch,
1494            Err(err) => {
1495                error!("Failed to initiate the MessageBatch: {:?}", err);
1496                return Err(err.into());
1497            }
1498        };
1499
1500        let producer_config = self.producer_config.snapshot();
1501        for message in &mut msg_batch.messages {
1502            Validators::check_message::<Message>(Some(message), &producer_config)?;
1503            MessageClientIDSetter::set_uniq_id(message);
1504            message.set_topic(self.with_namespace(message.topic()));
1505        }
1506        MessageClientIDSetter::set_uniq_id(&mut msg_batch.final_message);
1507        msg_batch.set_body(rocketmq_protocol::common::message::message_decoder::encode_messages(
1508            &msg_batch.messages,
1509        ));
1510        msg_batch.set_topic(self.with_namespace(msg_batch.topic()));
1511        Ok(msg_batch)
1512    }
1513
1514    #[inline]
1515    pub fn get_auto_batch(&self) -> bool {
1516        let producer_config = self.producer_config.snapshot();
1517        producer_config.produce_accumulator.is_some() && producer_config.auto_batch
1518    }
1519    #[inline]
1520    fn get_impl(&self) -> crate::ClientResult<&Arc<DefaultMQProducerImpl>> {
1521        self.default_mqproducer_impl
1522            .as_ref()
1523            .ok_or_else(|| mq_client_err!("DefaultMQProducerImpl is not initialized, call start() first"))
1524    }
1525
1526    #[inline]
1527    fn get_accumulator(&self) -> crate::ClientResult<Arc<ProduceAccumulator>> {
1528        self.producer_config
1529            .snapshot()
1530            .produce_accumulator
1531            .clone()
1532            .ok_or_else(|| mq_client_err!("ProduceAccumulator is not initialized, auto-batch is enabled"))
1533    }
1534    pub async fn send_direct<M>(
1535        &self,
1536        mut msg: M,
1537        mq: Option<MessageQueue>,
1538        send_callback: Option<ArcSendCallback>,
1539    ) -> crate::ClientResult<Option<SendResult>>
1540    where
1541        M: MessageTrait + Send + Sync,
1542    {
1543        let producer = self.get_impl()?;
1544
1545        if send_callback.is_none() {
1546            if let Some(mq) = mq {
1547                producer.sync_send_with_message_queue(msg, mq).await
1548            } else {
1549                producer.send(&mut msg).await
1550            }
1551        } else if let Some(mq) = mq {
1552            producer
1553                .async_send_with_message_queue_callback(msg, mq, send_callback)
1554                .await?;
1555            Ok(None)
1556        } else {
1557            producer.async_send_with_callback(msg, send_callback).await?;
1558            Ok(None)
1559        }
1560    }
1561
1562    pub async fn send_by_accumulator<M>(
1563        &self,
1564        mut msg: M,
1565        mq: Option<MessageQueue>,
1566        send_callback: Option<ArcSendCallback>,
1567    ) -> crate::ClientResult<Option<SendResult>>
1568    where
1569        M: MessageTrait + Send + std::marker::Sync + 'static,
1570    {
1571        let producer_config = self.producer_config_snapshot();
1572        Validators::check_message(Some(&msg), &producer_config)?;
1573        if !self.can_batch(&msg) {
1574            self.send_direct(msg, mq, send_callback).await
1575        } else {
1576            MessageClientIDSetter::set_uniq_id(&mut msg);
1577            if send_callback.is_none() {
1578                let mq_producer = self.clone();
1579                self.get_accumulator()?.send(msg, mq, mq_producer).await
1580            } else {
1581                let mq_producer = self.clone();
1582                self.get_accumulator()?
1583                    .send_callback(msg, mq, send_callback, mq_producer)
1584                    .await?;
1585                Ok(None)
1586            }
1587        }
1588    }
1589
1590    fn can_batch<M>(&self, msg: &M) -> bool
1591    where
1592        M: MessageTrait,
1593    {
1594        // delay message do not support batch processing
1595        if msg.delay_time_level() > 0
1596            || msg.get_delay_time_ms() > 0
1597            || msg.get_delay_time_sec() > 0
1598            || msg.get_deliver_time_ms() > 0
1599        {
1600            return false;
1601        }
1602        // retry message do not support batch processing
1603        if msg.topic().starts_with(mix_all::RETRY_GROUP_TOPIC_PREFIX) {
1604            return false;
1605        }
1606        // message which have been assigned to producer group do not support batch processing
1607        if msg.get_properties().contains_key(MessageConst::PROPERTY_PRODUCER_GROUP) {
1608            return false;
1609        }
1610        // produceAccumulator is full
1611        let producer_config = self.producer_config.snapshot();
1612        let Some(produce_accumulator) = producer_config.produce_accumulator.as_ref() else {
1613            return false;
1614        };
1615        if !produce_accumulator.try_add_message(msg) {
1616            return false;
1617        }
1618        true
1619    }
1620}
1621
1622impl DefaultMQProducer {
1623    #[inline]
1624    pub fn with_namespace(&self, resource: impl Into<CheetahString>) -> CheetahString {
1625        let resource = resource.into();
1626        let client_config = self.client_config.snapshot();
1627        let namespace = client_config.resolved_namespace().unwrap_or_default();
1628        if namespace.is_empty() || NamespaceUtil::is_already_with_namespace(resource.as_str(), namespace.as_str()) {
1629            return resource;
1630        }
1631        NamespaceUtil::wrap_namespace(namespace, resource)
1632    }
1633
1634    fn prepare_trace_dispatcher(&self, default_mqproducer_impl: &DefaultMQProducerImpl) -> Option<ArcTraceDispatcher> {
1635        let client_config = self.client_config.snapshot();
1636        let (dispatcher, rpc_hook) = self.producer_config.update(|producer_config| {
1637            let dispatcher = match producer_config.trace_dispatcher.clone() {
1638                Some(dispatcher) => dispatcher,
1639                None if client_config.enable_trace => {
1640                    let trace_topic = client_config
1641                        .trace_topic
1642                        .as_ref()
1643                        .map(|topic| topic.as_str())
1644                        .unwrap_or_default();
1645                    let dispatcher = AsyncTraceDispatcher::new(
1646                        default_mqproducer_impl
1647                            .client_runtime()
1648                            .expect("public producer implementation must retain its explicit ClientRuntime"),
1649                        producer_config.producer_group.as_str(),
1650                        Type::Produce,
1651                        client_config.trace_msg_batch_num,
1652                        trace_topic,
1653                        producer_config.rpc_hook.clone(),
1654                    );
1655                    Arc::new(dispatcher)
1656                }
1657                None => return None,
1658            };
1659
1660            producer_config.trace_dispatcher = Some(dispatcher.clone());
1661            let recall_trace_hook: Arc<dyn RPCHook> = Arc::new(DefaultRecallMessageTraceHook::new(dispatcher.clone()));
1662            let rpc_hook = match producer_config.rpc_hook.clone() {
1663                Some(existing_hook) => CompositeRPCHook::chain(existing_hook, recall_trace_hook),
1664                None => recall_trace_hook,
1665            };
1666            producer_config.rpc_hook = Some(rpc_hook.clone());
1667            Some((dispatcher, rpc_hook))
1668        })?;
1669
1670        if let Some(async_dispatcher) = dispatcher.as_any().downcast_ref::<AsyncTraceDispatcher>() {
1671            async_dispatcher.set_namespace_v2(client_config.namespace_v2.clone());
1672            async_dispatcher.set_use_tls(client_config.use_tls);
1673        }
1674
1675        default_mqproducer_impl.register_send_message_hook(Arc::new(SendMessageTraceHookImpl::new(dispatcher.clone())));
1676        default_mqproducer_impl
1677            .register_end_transaction_hook(Arc::new(EndTransactionTraceHookImpl::new(dispatcher.clone())));
1678        default_mqproducer_impl.set_rpc_hook(rpc_hook);
1679        self.sync_producer_config_to_impl();
1680
1681        Some(dispatcher)
1682    }
1683}
1684
1685impl ProducerBackend for DefaultMQProducer {
1686    async fn start(&mut self) -> crate::ClientResult<()> {
1687        let producer_group_clone = self.producer_config.snapshot().producer_group.clone();
1688        let producer_group = self.with_namespace(&producer_group_clone);
1689        self.set_producer_group(producer_group);
1690        let default_mqproducer_impl = self
1691            .default_mqproducer_impl
1692            .as_ref()
1693            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?;
1694
1695        let trace_dispatcher_to_start = self.prepare_trace_dispatcher(default_mqproducer_impl);
1696
1697        default_mqproducer_impl.start().await?;
1698        if let Some(dispatcher) = trace_dispatcher_to_start.as_ref() {
1699            if let Some(async_dispatcher) = dispatcher.as_any().downcast_ref::<AsyncTraceDispatcher>() {
1700                async_dispatcher.set_client_host(default_mqproducer_impl.client_id());
1701            }
1702        }
1703        let producer_config = self.producer_config.snapshot();
1704        if let Some(ref produce_accumulator) = producer_config.produce_accumulator {
1705            produce_accumulator.start()?;
1706        }
1707        if let Some(dispatcher) = trace_dispatcher_to_start {
1708            let client_config = self.client_config.snapshot();
1709            let name_server_addr = client_config
1710                .namesrv_addr
1711                .as_ref()
1712                .map(|addr| addr.as_str())
1713                .unwrap_or_default();
1714            if let Err(error) = dispatcher.start(name_server_addr, client_config.access_channel) {
1715                tracing::warn!("trace dispatcher start failed: {}", error);
1716            }
1717        }
1718        Ok(())
1719    }
1720
1721    async fn shutdown(&mut self) {
1722        if let Some(ref default_mqproducer_impl) = self.default_mqproducer_impl {
1723            if let Err(e) = default_mqproducer_impl.shutdown().await {
1724                error!("DefaultMQProducerImpl shutdown error: {:?}", e);
1725            }
1726        }
1727
1728        let producer_config = self.producer_config.snapshot();
1729        if let Some(ref produce_accumulator) = producer_config.produce_accumulator {
1730            produce_accumulator.shutdown_async().await;
1731        }
1732
1733        if let Some(ref trace_dispatcher) = producer_config.trace_dispatcher {
1734            if let Some(async_dispatcher) = trace_dispatcher.as_any().downcast_ref::<AsyncTraceDispatcher>() {
1735                async_dispatcher.shutdown_async().await;
1736            } else {
1737                trace_dispatcher.shutdown();
1738            }
1739        }
1740    }
1741
1742    async fn fetch_publish_message_queues(&mut self, topic: &str) -> crate::ClientResult<Vec<MessageQueue>> {
1743        let topic = self.with_namespace(topic);
1744        self.default_mqproducer_impl
1745            .as_ref()
1746            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1747            .fetch_publish_message_queues(topic.as_ref())
1748            .await
1749    }
1750
1751    async fn create_topic(
1752        &mut self,
1753        key: &str,
1754        new_topic: &str,
1755        queue_num: i32,
1756        attributes: HashMap<String, String>,
1757    ) -> crate::ClientResult<()> {
1758        self.create_topic_with_flag(key, new_topic, queue_num, 0, attributes)
1759            .await
1760    }
1761
1762    async fn create_topic_with_flag(
1763        &mut self,
1764        key: &str,
1765        new_topic: &str,
1766        queue_num: i32,
1767        topic_sys_flag: i32,
1768        attributes: HashMap<String, String>,
1769    ) -> crate::ClientResult<()> {
1770        let new_topic = self.with_namespace(new_topic);
1771        self.default_mqproducer_impl
1772            .as_ref()
1773            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1774            .create_topic(key, new_topic.as_str(), queue_num, topic_sys_flag, attributes)
1775            .await
1776    }
1777
1778    async fn search_offset(&mut self, mq: &MessageQueue, timestamp: u64) -> crate::ClientResult<i64> {
1779        self.default_mqproducer_impl
1780            .as_ref()
1781            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1782            .search_offset(mq, timestamp)
1783            .await
1784    }
1785
1786    async fn max_offset(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
1787        self.default_mqproducer_impl
1788            .as_ref()
1789            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1790            .max_offset(mq)
1791            .await
1792    }
1793
1794    async fn min_offset(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
1795        self.default_mqproducer_impl
1796            .as_ref()
1797            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1798            .min_offset(mq)
1799            .await
1800    }
1801
1802    async fn earliest_msg_store_time(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
1803        self.default_mqproducer_impl
1804            .as_ref()
1805            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1806            .earliest_msg_store_time(mq)
1807            .await
1808    }
1809
1810    async fn query_message(
1811        &mut self,
1812        topic: &str,
1813        key: &str,
1814        max_num: i32,
1815        begin: u64,
1816        end: u64,
1817    ) -> crate::ClientResult<QueryResult> {
1818        let topic = self.with_namespace(topic);
1819        self.default_mqproducer_impl
1820            .as_ref()
1821            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1822            .query_message(topic.as_str(), key, max_num, begin, end)
1823            .await
1824    }
1825
1826    async fn view_message(&mut self, topic: &str, msg_id: &str) -> crate::ClientResult<MessageExt> {
1827        let view_result = {
1828            let producer_impl = self
1829                .default_mqproducer_impl
1830                .as_ref()
1831                .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?;
1832            producer_impl.view_message(topic, msg_id).await
1833        };
1834        match view_result {
1835            Ok(message) => Ok(message),
1836            Err(_) => {
1837                let topic = self.with_namespace(topic);
1838                self.default_mqproducer_impl
1839                    .as_ref()
1840                    .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1841                    .query_message_by_uniq_key(topic.as_str(), msg_id)
1842                    .await
1843            }
1844        }
1845    }
1846
1847    async fn send<M>(&self, mut msg: M) -> crate::ClientResult<Option<SendResult>>
1848    where
1849        M: MessageTrait + Send + Sync,
1850    {
1851        msg.set_topic(self.with_namespace(msg.topic()));
1852        if self.get_auto_batch() && msg.as_any().downcast_ref::<MessageBatch>().is_none() {
1853            self.send_by_accumulator(msg, None, None).await
1854        } else {
1855            let timeout = self.send_msg_timeout() as u64;
1856            self.default_mqproducer_impl
1857                .as_ref()
1858                .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1859                .send_with_timeout(&mut msg, timeout)
1860                .await
1861        }
1862    }
1863
1864    async fn send_with_timeout<M>(&self, mut msg: M, timeout: u64) -> crate::ClientResult<Option<SendResult>>
1865    where
1866        M: MessageTrait + Send + Sync,
1867    {
1868        let topic_build = self.with_namespace(msg.topic().as_str());
1869        msg.set_topic(topic_build);
1870        self.default_mqproducer_impl
1871            .as_ref()
1872            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1873            .send_with_timeout(&mut msg, timeout)
1874            .await
1875    }
1876
1877    async fn send_with_callback<M, F>(&self, mut msg: M, send_callback: F) -> crate::ClientResult<()>
1878    where
1879        M: MessageTrait + Send + Sync,
1880        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
1881    {
1882        msg.set_topic(self.with_namespace(msg.topic()));
1883        let send_callback_inner = Arc::new(send_callback);
1884        let result = if self.get_auto_batch() && msg.as_any().downcast_ref::<MessageBatch>().is_none() {
1885            self.send_by_accumulator(msg, None, Some(send_callback_inner.clone()))
1886                .await
1887        } else {
1888            let timeout = self.send_msg_timeout() as u64;
1889            self.default_mqproducer_impl
1890                .as_ref()
1891                .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1892                .async_send_with_callback_timeout(msg, Some(send_callback_inner.clone()), timeout)
1893                .await
1894                .map(|()| None)
1895        };
1896        if let Err(err) = result {
1897            send_callback_inner(None, Some(&err));
1898        }
1899        Ok(())
1900    }
1901
1902    async fn send_with_callback_timeout<F, M>(
1903        &self,
1904        mut msg: M,
1905        send_callback: F,
1906        timeout: u64,
1907    ) -> crate::ClientResult<()>
1908    where
1909        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
1910        M: MessageTrait + Send + Sync,
1911    {
1912        msg.set_topic(self.with_namespace(msg.topic().as_str()));
1913        self.default_mqproducer_impl
1914            .as_ref()
1915            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1916            .async_send_with_callback_timeout(msg, Some(Arc::new(send_callback)), timeout)
1917            .await?;
1918        Ok(())
1919    }
1920
1921    async fn send_oneway<M>(&self, mut msg: M) -> crate::ClientResult<()>
1922    where
1923        M: MessageTrait + Send + Sync,
1924    {
1925        msg.set_topic(self.with_namespace(msg.topic()));
1926        self.default_mqproducer_impl
1927            .as_ref()
1928            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1929            .send_oneway(msg)
1930            .await?;
1931        Ok(())
1932    }
1933
1934    async fn send_to_queue<M>(&self, mut msg: M, mq: MessageQueue) -> crate::ClientResult<Option<SendResult>>
1935    where
1936        M: MessageTrait + Send + Sync,
1937    {
1938        msg.set_topic(self.with_namespace(msg.topic()));
1939        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
1940        if self.get_auto_batch() && msg.as_any().downcast_ref::<MessageBatch>().is_none() {
1941            self.send_by_accumulator(msg, Some(mq), None).await
1942        } else {
1943            self.send_direct(msg, Some(mq), None).await
1944        }
1945    }
1946
1947    async fn send_to_queue_with_timeout<M>(
1948        &self,
1949        mut msg: M,
1950        mq: MessageQueue,
1951        timeout: u64,
1952    ) -> crate::ClientResult<Option<SendResult>>
1953    where
1954        M: MessageTrait + Send + Sync,
1955    {
1956        msg.set_topic(self.with_namespace(msg.topic()));
1957        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
1958        self.default_mqproducer_impl
1959            .as_ref()
1960            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
1961            .sync_send_with_message_queue_timeout(msg, mq, timeout)
1962            .await
1963    }
1964
1965    async fn send_to_queue_with_callback<M, F>(
1966        &self,
1967        mut msg: M,
1968        mq: MessageQueue,
1969        send_callback: F,
1970    ) -> crate::ClientResult<()>
1971    where
1972        M: MessageTrait + Send + Sync,
1973        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
1974    {
1975        msg.set_topic(self.with_namespace(msg.topic()));
1976        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
1977
1978        if self.get_auto_batch() && msg.as_any().downcast_ref::<MessageBatch>().is_none() {
1979            self.send_by_accumulator(msg, Some(mq), Some(Arc::new(send_callback)))
1980                .await
1981        } else {
1982            self.send_direct(msg, Some(mq), Some(Arc::new(send_callback))).await
1983        }?;
1984
1985        Ok(())
1986    }
1987
1988    async fn send_to_queue_with_callback_timeout<M, F>(
1989        &self,
1990        mut msg: M,
1991        mq: MessageQueue,
1992        send_callback: F,
1993        timeout: u64,
1994    ) -> crate::ClientResult<()>
1995    where
1996        M: MessageTrait + Send + Sync,
1997        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
1998    {
1999        msg.set_topic(self.with_namespace(msg.topic()));
2000        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2001        self.default_mqproducer_impl
2002            .as_ref()
2003            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2004            .async_send_batch_to_queue_with_callback_timeout(msg, mq, Some(Arc::new(send_callback)), timeout)
2005            .await
2006    }
2007
2008    async fn send_oneway_to_queue<M>(&self, mut msg: M, mq: MessageQueue) -> crate::ClientResult<()>
2009    where
2010        M: MessageTrait + Send + Sync,
2011    {
2012        msg.set_topic(self.with_namespace(msg.topic()));
2013        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2014        self.default_mqproducer_impl
2015            .as_ref()
2016            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2017            .send_oneway_with_message_queue(msg, mq)
2018            .await?;
2019        Ok(())
2020    }
2021
2022    async fn send_with_selector<M, S, T>(
2023        &self,
2024        mut msg: M,
2025        selector: S,
2026        arg: T,
2027    ) -> crate::ClientResult<Option<SendResult>>
2028    where
2029        M: MessageTrait + Send + Sync,
2030        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
2031        T: Send + Sync,
2032    {
2033        msg.set_topic(self.with_namespace(msg.topic()));
2034        let mq = self
2035            .default_mqproducer_impl
2036            .as_ref()
2037            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2038            .invoke_message_queue_selector(&mut msg, selector, &arg, self.send_msg_timeout() as u64)
2039            .await?;
2040        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2041        if self.get_auto_batch() && msg.as_any().downcast_ref::<MessageBatch>().is_none() {
2042            self.send_by_accumulator(msg, Some(mq), None).await
2043        } else {
2044            self.send_direct(msg, Some(mq), None).await
2045        }
2046    }
2047
2048    async fn send_with_selector_timeout<M, S, T>(
2049        &self,
2050        mut msg: M,
2051        selector: S,
2052        arg: T,
2053        timeout: u64,
2054    ) -> crate::ClientResult<Option<SendResult>>
2055    where
2056        M: MessageTrait + Send + Sync,
2057        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
2058        T: Send + Sync,
2059    {
2060        msg.set_topic(self.with_namespace(msg.topic()));
2061        self.default_mqproducer_impl
2062            .as_ref()
2063            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2064            .send_with_selector_timeout(msg, selector, arg, timeout)
2065            .await
2066    }
2067
2068    async fn send_with_selector_callback<M, S, T>(
2069        &self,
2070        mut msg: M,
2071        selector: S,
2072        arg: T,
2073        send_callback: Option<ArcSendCallback>,
2074    ) -> crate::ClientResult<()>
2075    where
2076        M: MessageTrait + Send + Sync,
2077        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
2078        T: Send + Sync,
2079    {
2080        msg.set_topic(self.with_namespace(msg.topic()));
2081        let mq = self
2082            .default_mqproducer_impl
2083            .as_ref()
2084            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2085            .invoke_message_queue_selector(&mut msg, selector, &arg, self.send_msg_timeout() as u64)
2086            .await?;
2087        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2088        if self.auto_batch() && msg.as_any().downcast_ref::<MessageBatch>().is_none() {
2089            self.send_by_accumulator(msg, Some(mq), send_callback).await
2090        } else {
2091            self.send_direct(msg, Some(mq), send_callback).await
2092        }?;
2093        Ok(())
2094    }
2095
2096    async fn send_with_selector_callback_timeout<M, S, T>(
2097        &self,
2098        mut msg: M,
2099        selector: S,
2100        arg: T,
2101        send_callback: Option<ArcSendCallback>,
2102        timeout: u64,
2103    ) -> crate::ClientResult<()>
2104    where
2105        M: MessageTrait + Send + Sync,
2106        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
2107        T: Send + Sync + 'static,
2108    {
2109        msg.set_topic(self.with_namespace(msg.topic()));
2110        self.default_mqproducer_impl
2111            .as_ref()
2112            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2113            .send_with_selector_callback_timeout(msg, selector, arg, send_callback, timeout)
2114            .await
2115    }
2116
2117    async fn send_oneway_with_selector<M, S, T>(&self, mut msg: M, selector: S, arg: T) -> crate::ClientResult<()>
2118    where
2119        M: MessageTrait + Send + Sync,
2120        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
2121        T: Send + Sync + 'static,
2122    {
2123        msg.set_topic(self.with_namespace(msg.topic()));
2124        self.default_mqproducer_impl
2125            .as_ref()
2126            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2127            .send_oneway_with_selector(msg, selector, arg)
2128            .await
2129    }
2130
2131    async fn send_message_in_transaction<T, M>(
2132        &self,
2133        _msg: M,
2134        _arg: Option<T>,
2135    ) -> crate::ClientResult<TransactionSendResult>
2136    where
2137        T: std::any::Any + Sync + Send,
2138        M: MessageTrait + Send + Sync,
2139    {
2140        Err(crate::mq_client_err!(
2141            "sendMessageInTransaction not implement, please use TransactionMQProducer class"
2142        ))
2143    }
2144
2145    async fn send_batch<M>(&self, msgs: Vec<M>) -> crate::ClientResult<SendResult>
2146    where
2147        M: MessageTrait + Send + Sync,
2148    {
2149        let mut batch = self.batch(msgs)?;
2150        let result = self
2151            .default_mqproducer_impl
2152            .as_ref()
2153            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2154            .send(&mut batch)
2155            .await?;
2156        result.ok_or_else(|| crate::mq_client_err!("Synchronous batch send completed without SendResult"))
2157    }
2158
2159    async fn send_batch_with_timeout<M>(&self, msgs: Vec<M>, timeout: u64) -> crate::ClientResult<SendResult>
2160    where
2161        M: MessageTrait + Send + Sync,
2162    {
2163        let mut batch = self.batch(msgs)?;
2164        let result = self
2165            .default_mqproducer_impl
2166            .as_ref()
2167            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2168            .send_with_timeout(&mut batch, timeout)
2169            .await?;
2170        result.ok_or_else(|| crate::mq_client_err!("Synchronous batch send completed without SendResult"))
2171    }
2172
2173    async fn send_batch_to_queue<M>(&self, msgs: Vec<M>, mq: MessageQueue) -> crate::ClientResult<SendResult>
2174    where
2175        M: MessageTrait + Send + Sync,
2176    {
2177        let batch = self.batch(msgs)?;
2178        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2179        let result = self
2180            .default_mqproducer_impl
2181            .as_ref()
2182            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2183            .sync_send_with_message_queue(batch, mq)
2184            .await?;
2185        result.ok_or_else(|| crate::mq_client_err!("Synchronous batch send completed without SendResult"))
2186    }
2187
2188    async fn send_batch_to_queue_with_timeout<M>(
2189        &self,
2190        msgs: Vec<M>,
2191        mq: MessageQueue,
2192        timeout: u64,
2193    ) -> crate::ClientResult<SendResult>
2194    where
2195        M: MessageTrait + Send + Sync,
2196    {
2197        let batch = self.batch(msgs)?;
2198        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2199        let result = self
2200            .default_mqproducer_impl
2201            .as_ref()
2202            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2203            .sync_send_with_message_queue_timeout(batch, mq, timeout)
2204            .await?;
2205        result.ok_or_else(|| crate::mq_client_err!("Synchronous batch send completed without SendResult"))
2206    }
2207
2208    async fn send_batch_with_callback<M, F>(&self, msgs: Vec<M>, f: F) -> crate::ClientResult<()>
2209    where
2210        M: MessageTrait + Send + Sync,
2211        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
2212    {
2213        let batch = self.batch(msgs)?;
2214        self.default_mqproducer_impl
2215            .as_ref()
2216            .ok_or_else(|| crate::ClientError::not_initialized("DefaultMQProducerImpl is not initialized"))?
2217            .async_send_with_callback(batch, Some(Arc::new(f)))
2218            .await?;
2219        Ok(())
2220    }
2221
2222    async fn send_batch_with_callback_timeout<M, F>(&self, msgs: Vec<M>, f: F, timeout: u64) -> crate::ClientResult<()>
2223    where
2224        M: MessageTrait + Send + Sync,
2225        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
2226    {
2227        let batch = self.batch(msgs)?;
2228        self.default_mqproducer_impl
2229            .as_ref()
2230            .ok_or_else(|| crate::ClientError::not_initialized("DefaultMQProducerImpl is not initialized"))?
2231            .async_send_with_callback_timeout(batch, Some(Arc::new(f)), timeout)
2232            .await?;
2233        Ok(())
2234    }
2235
2236    async fn send_batch_to_queue_with_callback<M, F>(
2237        &self,
2238        msgs: Vec<M>,
2239        mq: MessageQueue,
2240        f: F,
2241    ) -> crate::ClientResult<()>
2242    where
2243        M: MessageTrait + Send + Sync,
2244        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
2245    {
2246        let batch = self.batch(msgs)?;
2247        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2248        self.default_mqproducer_impl
2249            .as_ref()
2250            .ok_or_else(|| crate::ClientError::not_initialized("DefaultMQProducerImpl is not initialized"))?
2251            .async_send_with_message_queue_callback(batch, mq, Some(Arc::new(f)))
2252            .await
2253    }
2254
2255    async fn send_batch_to_queue_with_callback_timeout<M, F>(
2256        &self,
2257        msgs: Vec<M>,
2258        mq: MessageQueue,
2259        f: F,
2260        timeout: u64,
2261    ) -> crate::ClientResult<()>
2262    where
2263        M: MessageTrait + Send + Sync,
2264        F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
2265    {
2266        let batch = self.batch(msgs)?;
2267        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2268        self.default_mqproducer_impl
2269            .as_ref()
2270            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2271            .async_send_batch_to_queue_with_callback_timeout(batch, mq, Some(Arc::new(f)), timeout)
2272            .await
2273    }
2274
2275    async fn request<M>(&self, mut msg: M, timeout: u64) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
2276    where
2277        M: MessageTrait + Send + Sync,
2278    {
2279        msg.set_topic(self.with_namespace(msg.topic()));
2280        self.default_mqproducer_impl
2281            .as_ref()
2282            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2283            .request(msg, timeout)
2284            .await
2285    }
2286
2287    async fn request_with_callback<F, M>(
2288        &self,
2289        mut msg: M,
2290        request_callback: F,
2291        timeout: u64,
2292    ) -> crate::ClientResult<()>
2293    where
2294        F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
2295        M: MessageTrait + Send + Sync,
2296    {
2297        msg.set_topic(self.with_namespace(msg.topic()));
2298        self.default_mqproducer_impl
2299            .as_ref()
2300            .ok_or_else(|| crate::ClientError::not_initialized("DefaultMQProducerImpl is not initialized"))?
2301            .request_with_callback(msg, Arc::new(request_callback), timeout)
2302            .await
2303    }
2304
2305    async fn request_with_selector<M, S, T>(
2306        &self,
2307        mut msg: M,
2308        selector: S,
2309        arg: T,
2310        timeout: u64,
2311    ) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
2312    where
2313        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
2314        T: Send + Sync + 'static,
2315        M: MessageTrait + Send + Sync,
2316    {
2317        msg.set_topic(self.with_namespace(msg.topic()));
2318        self.default_mqproducer_impl
2319            .as_ref()
2320            .ok_or_else(|| crate::ClientError::not_initialized("DefaultMQProducerImpl is not initialized"))?
2321            .request_with_selector(msg, selector, arg, timeout)
2322            .await
2323    }
2324
2325    async fn request_with_selector_callback<M, S, T, F>(
2326        &self,
2327        mut msg: M,
2328        selector: S,
2329        arg: T,
2330        request_callback: F,
2331        timeout: u64,
2332    ) -> crate::ClientResult<()>
2333    where
2334        S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
2335        F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
2336        T: Send + Sync + 'static,
2337        M: MessageTrait + Send + Sync,
2338    {
2339        msg.set_topic(self.with_namespace(msg.topic()));
2340        self.default_mqproducer_impl
2341            .as_ref()
2342            .ok_or_else(|| crate::ClientError::not_initialized("DefaultMQProducerImpl is not initialized"))?
2343            .request_with_selector_callback(msg, selector, arg, Arc::new(request_callback), timeout)
2344            .await
2345    }
2346
2347    async fn request_to_queue<M>(
2348        &self,
2349        mut msg: M,
2350        mq: MessageQueue,
2351        timeout: u64,
2352    ) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
2353    where
2354        M: MessageTrait + Send + Sync,
2355    {
2356        msg.set_topic(self.with_namespace(msg.topic()));
2357        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2358        self.default_mqproducer_impl
2359            .as_ref()
2360            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2361            .request_to_queue(msg, mq, timeout)
2362            .await
2363    }
2364
2365    async fn request_to_queue_with_callback<M, F>(
2366        &self,
2367        mut msg: M,
2368        mq: MessageQueue,
2369        request_callback: F,
2370        timeout: u64,
2371    ) -> crate::ClientResult<()>
2372    where
2373        F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
2374        M: MessageTrait + Send + Sync,
2375    {
2376        msg.set_topic(self.with_namespace(msg.topic()));
2377        let mq = self.client_config.snapshot().queue_with_resolved_namespace(mq);
2378        self.default_mqproducer_impl
2379            .as_ref()
2380            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2381            .request_to_queue_with_callback(msg, mq, Arc::new(request_callback), timeout)
2382            .await
2383    }
2384
2385    fn as_any(&self) -> &dyn std::any::Any {
2386        self
2387    }
2388
2389    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
2390        self
2391    }
2392
2393    async fn recall_message(
2394        &self,
2395        topic: impl Into<CheetahString>,
2396        recall_handle: impl Into<CheetahString>,
2397    ) -> crate::ClientResult<String> {
2398        self.default_mqproducer_impl
2399            .as_ref()
2400            .ok_or(ClientError::not_initialized("DefaultMQProducerImpl not initialized"))?
2401            .recall_message(topic, recall_handle)
2402            .await
2403    }
2404}
2405
2406#[cfg(test)]
2407mod facade_tests {
2408    use std::sync::Arc;
2409
2410    use crate::ClientError;
2411    use crate::ClientResult;
2412    use bytes::Bytes;
2413    use rocketmq_model::common::message::message_queue::MessageQueue;
2414    use rocketmq_model::common::message::message_single::Message;
2415    use rocketmq_model::common::message::MessageTrait;
2416
2417    use super::DefaultMQProducer;
2418    use super::ProducerConfig;
2419    use super::StableConfig;
2420    use crate::base::client_config::ClientConfig;
2421    use crate::producer::producer_backend::ProducerBackend;
2422    use crate::producer::send_result::SendResult;
2423
2424    fn test_runtime() -> Arc<crate::runtime::ClientRuntime> {
2425        crate::runtime::test_client_runtime("default-producer-facade-test")
2426    }
2427
2428    fn unstarted_producer() -> DefaultMQProducer {
2429        DefaultMQProducer {
2430            session: None,
2431            client_config: StableConfig::new(ClientConfig::default()),
2432            producer_config: StableConfig::new(ProducerConfig::default()),
2433            default_mqproducer_impl: None,
2434        }
2435    }
2436
2437    #[test]
2438    fn cloned_facades_share_standard_impl_root_without_self_cycle() {
2439        let producer = DefaultMQProducer::builder(test_runtime())
2440            .producer_group("facade_standard_arc_root")
2441            .build();
2442        let producer_clone = producer.clone();
2443        let root = producer
2444            .default_mqproducer_impl
2445            .as_ref()
2446            .expect("producer impl should be initialized")
2447            .clone();
2448        let weak = Arc::downgrade(&root);
2449
2450        assert!(Arc::ptr_eq(
2451            producer
2452                .default_mqproducer_impl
2453                .as_ref()
2454                .expect("producer impl should be initialized"),
2455            producer_clone
2456                .default_mqproducer_impl
2457                .as_ref()
2458                .expect("cloned producer impl should be initialized"),
2459        ));
2460
2461        drop(root);
2462        drop(producer);
2463        assert!(weak.upgrade().is_some(), "the cloned facade should keep the root alive");
2464
2465        drop(producer_clone);
2466        assert!(
2467            weak.upgrade().is_none(),
2468            "the standard weak self reference must not form a cycle"
2469        );
2470    }
2471
2472    #[test]
2473    fn cloned_facades_publish_updates_from_the_latest_shared_config_generation() {
2474        let mut first = DefaultMQProducer::builder(test_runtime())
2475            .producer_group("facade_shared_config")
2476            .build();
2477        let mut second = first.clone();
2478
2479        first.set_send_msg_timeout(4_321);
2480        second.set_retry_times_when_send_failed(5);
2481        first.set_latency_max(vec![10, 20, 30]);
2482
2483        assert_eq!(first.get_retry_times_when_send_failed(), 5);
2484        assert_eq!(second.get_send_msg_timeout(), 4_321);
2485        assert_eq!(second.latency_max(), &[10, 20, 30]);
2486
2487        let producer_impl = first
2488            .default_mqproducer_impl
2489            .as_ref()
2490            .expect("producer impl should be initialized");
2491        let impl_config = producer_impl.producer_config();
2492        assert_eq!(impl_config.send_msg_timeout(), 4_321);
2493        assert_eq!(impl_config.retry_times_when_send_failed(), 5);
2494        assert_eq!(producer_impl.latency_max(), &[10, 20, 30]);
2495    }
2496
2497    #[test]
2498    fn borrowed_config_generation_remains_valid_after_clone_updates() {
2499        let first = DefaultMQProducer::builder(test_runtime())
2500            .producer_group("facade_stable_borrow")
2501            .build();
2502        let mut second = first.clone();
2503        let original_latency = first.latency_max();
2504
2505        for latency in 1..=128 {
2506            second.set_latency_max(vec![latency]);
2507        }
2508
2509        assert_eq!(
2510            original_latency,
2511            crate::latency::mq_fault_strategy::MQFaultStrategy::DEFAULT_LATENCY_MAX
2512        );
2513        assert_eq!(first.latency_max(), &[128]);
2514    }
2515
2516    #[test]
2517    fn high_frequency_snapshot_updates_publish_only_the_current_generation() {
2518        let config = StableConfig::new(0_u64);
2519        let original = config.snapshot();
2520
2521        for value in 1..=10_000 {
2522            config.replace(value);
2523            assert_eq!(*config.snapshot(), value);
2524        }
2525
2526        assert_eq!(*original, 0);
2527        assert_eq!(*config.snapshot(), 10_000);
2528    }
2529
2530    fn message() -> Message {
2531        Message::builder()
2532            .topic("test-topic")
2533            .body(Bytes::from_static(b"facade"))
2534            .build_unchecked()
2535    }
2536
2537    fn queue() -> MessageQueue {
2538        MessageQueue::from_parts("test-topic", "broker-a", 0)
2539    }
2540
2541    fn test_send_callback(_result: Option<&SendResult>, _err: Option<&ClientError>) {}
2542
2543    fn test_request_callback(_msg: Option<&dyn MessageTrait>, _err: Option<&crate::ClientError>) {}
2544
2545    fn test_selector(_queues: &[MessageQueue], _msg: &Message, _arg: &i32) -> Option<MessageQueue> {
2546        None
2547    }
2548
2549    fn assert_not_initialized<T>(result: ClientResult<T>) {
2550        match result {
2551            Err(error) => assert!(
2552                error.is(&rocketmq_error::CORE_LIFECYCLE_NOT_INITIALIZED),
2553                "unexpected error: {error:?}"
2554            ),
2555            Ok(_) => panic!("expected producer facade to require a started implementation"),
2556        }
2557    }
2558
2559    fn assert_shared_borrow_contract_rejects<T>(result: ClientResult<T>) {
2560        assert!(
2561            result.is_err(),
2562            "expected shared-borrow ProducerBackend method to reject an unstarted producer"
2563        );
2564    }
2565
2566    #[tokio::test]
2567    async fn default_mq_producer_exposes_modern_java_send_facade_methods_without_trait_import() {
2568        assert_not_initialized(unstarted_producer().send(message()).await);
2569        assert_not_initialized(unstarted_producer().send_with_timeout(message(), 1000).await);
2570        assert_not_initialized(
2571            unstarted_producer()
2572                .send_to_queue_with_timeout(message(), queue(), 1000)
2573                .await,
2574        );
2575        assert_not_initialized(unstarted_producer().send_oneway_to_queue(message(), queue()).await);
2576
2577        let selector = |_queues: &[MessageQueue], _msg: &Message, _arg: &i32| -> Option<MessageQueue> { None };
2578        assert_not_initialized(
2579            unstarted_producer()
2580                .send_with_selector_timeout(message(), selector, 1, 1000)
2581                .await,
2582        );
2583
2584        let callback = |_result: Option<&SendResult>, _err: Option<&ClientError>| {};
2585        assert_not_initialized(
2586            unstarted_producer()
2587                .send_batch_to_queue_with_callback_timeout(vec![message()], queue(), callback, 1000)
2588                .await,
2589        );
2590    }
2591
2592    #[tokio::test]
2593    async fn default_mq_producer_satisfies_shared_borrow_producer_backend_send_contract() {
2594        let producer = unstarted_producer();
2595
2596        assert_shared_borrow_contract_rejects(ProducerBackend::send(&producer, message()).await);
2597        assert_shared_borrow_contract_rejects(ProducerBackend::send_with_timeout(&producer, message(), 1000).await);
2598        assert_shared_borrow_contract_rejects(
2599            ProducerBackend::send_with_callback(&producer, message(), test_send_callback).await,
2600        );
2601        assert_shared_borrow_contract_rejects(
2602            ProducerBackend::send_with_callback_timeout(&producer, message(), test_send_callback, 1000).await,
2603        );
2604        assert_shared_borrow_contract_rejects(ProducerBackend::send_oneway(&producer, message()).await);
2605        assert_shared_borrow_contract_rejects(ProducerBackend::send_to_queue(&producer, message(), queue()).await);
2606        assert_shared_borrow_contract_rejects(
2607            ProducerBackend::send_to_queue_with_timeout(&producer, message(), queue(), 1000).await,
2608        );
2609        assert_shared_borrow_contract_rejects(
2610            ProducerBackend::send_to_queue_with_callback(&producer, message(), queue(), test_send_callback).await,
2611        );
2612        assert_shared_borrow_contract_rejects(
2613            ProducerBackend::send_to_queue_with_callback_timeout(
2614                &producer,
2615                message(),
2616                queue(),
2617                test_send_callback,
2618                1000,
2619            )
2620            .await,
2621        );
2622        assert_shared_borrow_contract_rejects(
2623            ProducerBackend::send_with_selector(&producer, message(), test_selector, 1).await,
2624        );
2625        assert_shared_borrow_contract_rejects(
2626            ProducerBackend::send_with_selector_timeout(&producer, message(), test_selector, 1, 1000).await,
2627        );
2628        assert_shared_borrow_contract_rejects(
2629            ProducerBackend::send_with_selector_callback(
2630                &producer,
2631                message(),
2632                test_selector,
2633                1,
2634                Some(Arc::new(test_send_callback)),
2635            )
2636            .await,
2637        );
2638        assert_shared_borrow_contract_rejects(
2639            ProducerBackend::send_with_selector_callback_timeout(
2640                &producer,
2641                message(),
2642                test_selector,
2643                1,
2644                Some(Arc::new(test_send_callback)),
2645                1000,
2646            )
2647            .await,
2648        );
2649        assert_shared_borrow_contract_rejects(ProducerBackend::send_batch(&producer, vec![message()]).await);
2650        assert_shared_borrow_contract_rejects(
2651            ProducerBackend::send_batch_with_timeout(&producer, vec![message()], 1000).await,
2652        );
2653        assert_shared_borrow_contract_rejects(
2654            ProducerBackend::send_batch_with_callback(&producer, vec![message()], test_send_callback).await,
2655        );
2656        assert_shared_borrow_contract_rejects(
2657            ProducerBackend::send_batch_with_callback_timeout(&producer, vec![message()], test_send_callback, 1000)
2658                .await,
2659        );
2660        assert_shared_borrow_contract_rejects(
2661            ProducerBackend::send_batch_to_queue(&producer, vec![message()], queue()).await,
2662        );
2663        assert_shared_borrow_contract_rejects(
2664            ProducerBackend::send_batch_to_queue_with_timeout(&producer, vec![message()], queue(), 1000).await,
2665        );
2666        assert_shared_borrow_contract_rejects(
2667            ProducerBackend::send_batch_to_queue_with_callback(&producer, vec![message()], queue(), test_send_callback)
2668                .await,
2669        );
2670        assert_shared_borrow_contract_rejects(
2671            ProducerBackend::send_batch_to_queue_with_callback_timeout(
2672                &producer,
2673                vec![message()],
2674                queue(),
2675                test_send_callback,
2676                1000,
2677            )
2678            .await,
2679        );
2680        assert_shared_borrow_contract_rejects(
2681            ProducerBackend::recall_message(&producer, "test-topic", "recall-handle-123").await,
2682        );
2683    }
2684
2685    #[tokio::test]
2686    async fn default_mq_producer_satisfies_shared_borrow_producer_backend_request_contract() {
2687        let producer = unstarted_producer();
2688
2689        assert_shared_borrow_contract_rejects(ProducerBackend::request(&producer, message(), 1000).await);
2690        assert_shared_borrow_contract_rejects(
2691            ProducerBackend::request_with_callback(&producer, message(), test_request_callback, 1000).await,
2692        );
2693        assert_shared_borrow_contract_rejects(
2694            ProducerBackend::request_with_selector(&producer, message(), test_selector, 1, 1000).await,
2695        );
2696        assert_shared_borrow_contract_rejects(
2697            ProducerBackend::request_with_selector_callback(
2698                &producer,
2699                message(),
2700                test_selector,
2701                1,
2702                test_request_callback,
2703                1000,
2704            )
2705            .await,
2706        );
2707        assert_shared_borrow_contract_rejects(
2708            ProducerBackend::request_to_queue(&producer, message(), queue(), 1000).await,
2709        );
2710        assert_shared_borrow_contract_rejects(
2711            ProducerBackend::request_to_queue_with_callback(&producer, message(), queue(), test_request_callback, 1000)
2712                .await,
2713        );
2714    }
2715
2716    #[tokio::test]
2717    async fn default_mq_producer_exposes_modern_java_request_facade_methods_without_trait_import() {
2718        let request_callback = |_msg: Option<&dyn MessageTrait>, _err: Option<&crate::ClientError>| {};
2719        assert_not_initialized(
2720            unstarted_producer()
2721                .request_with_callback(message(), request_callback, 1000)
2722                .await,
2723        );
2724
2725        let selector = |_queues: &[MessageQueue], _msg: &Message, _arg: &i32| -> Option<MessageQueue> { None };
2726        assert_not_initialized(
2727            unstarted_producer()
2728                .request_with_selector(message(), selector, 1, 1000)
2729                .await,
2730        );
2731
2732        assert_not_initialized(unstarted_producer().request_to_queue(message(), queue(), 1000).await);
2733
2734        let request_callback = |_msg: Option<&dyn MessageTrait>, _err: Option<&crate::ClientError>| {};
2735        assert_not_initialized(
2736            unstarted_producer()
2737                .request_to_queue_with_callback(message(), queue(), request_callback, 1000)
2738                .await,
2739        );
2740    }
2741}
2742
2743#[cfg(test)]
2744mod tests {
2745    use super::*;
2746    use crate::test_support::error_assertions::assert_invalid_argument;
2747    use crate::test_support::error_assertions::client_exception;
2748    use crate::ClientResult;
2749    use bytes::Bytes;
2750    use rocketmq_model::common::message::message_single::Message;
2751
2752    fn test_runtime() -> Arc<ClientRuntime> {
2753        crate::runtime::test_client_runtime("default-producer-test")
2754    }
2755    #[tokio::test]
2756    async fn request_with_callback_not_initialized() {
2757        // Arrange
2758        let producer = DefaultMQProducer {
2759            session: None,
2760            client_config: Default::default(),
2761            producer_config: Default::default(),
2762            default_mqproducer_impl: None,
2763        };
2764        let msg = Message::builder().topic("test-topic").empty_body().build_unchecked();
2765        let callback = |_msg: Option<&dyn MessageTrait>, _err: Option<&crate::ClientError>| {
2766            // no-op
2767        };
2768        let result = producer.request_with_callback(msg, callback, 1000).await;
2769        assert!(result.is_err());
2770        let err = result.unwrap_err();
2771        assert!(err.is(&rocketmq_error::CORE_LIFECYCLE_NOT_INITIALIZED));
2772    }
2773
2774    #[tokio::test]
2775    async fn request_with_selector_not_initialized() {
2776        // Arrange
2777        let producer = DefaultMQProducer {
2778            session: None,
2779            client_config: Default::default(),
2780            producer_config: Default::default(),
2781            default_mqproducer_impl: None,
2782        };
2783        let msg = Message::builder().topic("test-topic").empty_body().build_unchecked();
2784        let selector = |_queues: &[MessageQueue], _msg: &Message, _arg: &i32| -> Option<MessageQueue> { None };
2785        let result = producer.request_with_selector(msg, selector, 1, 1000).await;
2786        assert!(result.is_err());
2787        let err = result.unwrap_err();
2788        assert!(err.is(&rocketmq_error::CORE_LIFECYCLE_NOT_INITIALIZED));
2789    }
2790
2791    #[tokio::test]
2792    async fn request_with_selector_callback_not_initialized() {
2793        // Arrange
2794        let producer = DefaultMQProducer {
2795            session: None,
2796            client_config: Default::default(),
2797            producer_config: Default::default(),
2798            default_mqproducer_impl: None,
2799        };
2800        let msg = Message::builder().topic("test-topic").empty_body().build_unchecked();
2801        let selector = |_queues: &[MessageQueue], _msg: &Message, _arg: &i32| -> Option<MessageQueue> { None };
2802        let callback = |_msg: Option<&dyn MessageTrait>, _err: Option<&crate::ClientError>| {
2803            // no-op
2804        };
2805        let result = producer
2806            .request_with_selector_callback(msg, selector, 1, callback, 1000)
2807            .await;
2808        assert!(result.is_err());
2809        let err = result.unwrap_err();
2810        assert!(err.is(&rocketmq_error::CORE_LIFECYCLE_NOT_INITIALIZED));
2811    }
2812
2813    #[tokio::test]
2814    async fn send_batch_with_callback_not_initialized() {
2815        // Arrange
2816        let producer = DefaultMQProducer {
2817            session: None,
2818            client_config: Default::default(),
2819            producer_config: Default::default(),
2820            default_mqproducer_impl: None,
2821        };
2822        let msg = Message::builder()
2823            .topic("test-topic")
2824            .body(Bytes::from_static(b"Hello world"))
2825            .build_unchecked();
2826        let callback = |_msg: Option<&SendResult>, _err: Option<&ClientError>| {
2827            // no-op
2828        };
2829        let result: ClientResult<()> = producer.send_batch_with_callback(vec![msg], callback).await;
2830        assert!(result.is_err());
2831        let err = result.unwrap_err();
2832        assert!(err.is(&rocketmq_error::CORE_LIFECYCLE_NOT_INITIALIZED));
2833    }
2834
2835    #[tokio::test]
2836    async fn send_batch_delay_millis_returns_java_compatible_batch_error_before_start_check() {
2837        let producer = DefaultMQProducer {
2838            session: None,
2839            client_config: Default::default(),
2840            producer_config: Default::default(),
2841            default_mqproducer_impl: None,
2842        };
2843        let msg1 = Message::builder()
2844            .topic("test-topic")
2845            .body(Bytes::from_static(b"Hello world"))
2846            .build_unchecked();
2847        let msg2 = Message::builder()
2848            .topic("test-topic")
2849            .body(Bytes::from_static(b"Delayed"))
2850            .delay_millis(1000)
2851            .build_unchecked();
2852
2853        let result = producer.send_batch(vec![msg1, msg2]).await;
2854
2855        let err = result.expect_err("delayed batch message should be rejected before send");
2856        assert_invalid_argument(&err);
2857    }
2858
2859    #[tokio::test]
2860    async fn default_producer_transaction_send_returns_java_compatible_error() {
2861        let producer = DefaultMQProducer {
2862            session: None,
2863            client_config: Default::default(),
2864            producer_config: Default::default(),
2865            default_mqproducer_impl: None,
2866        };
2867        let msg = Message::builder()
2868            .topic("test-topic")
2869            .body(Bytes::from_static(b"transaction"))
2870            .build_unchecked();
2871
2872        let result = producer.send_message_in_transaction(msg, Option::<()>::None).await;
2873
2874        let err = result.expect_err("DefaultMQProducer should reject transaction sends");
2875        assert!(
2876            client_exception(&err)
2877                .to_string()
2878                .contains("sendMessageInTransaction not implement, please use TransactionMQProducer class"),
2879            "unexpected error message: {err}"
2880        );
2881    }
2882
2883    #[tokio::test]
2884    async fn send_batch_with_callback_timeout_not_initialized() {
2885        // Arrange
2886        let producer = DefaultMQProducer {
2887            session: None,
2888            client_config: Default::default(),
2889            producer_config: Default::default(),
2890            default_mqproducer_impl: None,
2891        };
2892        let msg = Message::builder()
2893            .topic("test-topic")
2894            .body(Bytes::from_static(b"Hello world"))
2895            .build_unchecked();
2896        let callback = |_msg: Option<&SendResult>, _err: Option<&ClientError>| {
2897            // no-op
2898        };
2899        let result: ClientResult<()> = producer
2900            .send_batch_with_callback_timeout(vec![msg], callback, 1000)
2901            .await;
2902        assert!(result.is_err());
2903        let err = result.unwrap_err();
2904        assert!(err.is(&rocketmq_error::CORE_LIFECYCLE_NOT_INITIALIZED));
2905    }
2906
2907    #[tokio::test]
2908    async fn send_batch_to_queue_with_callback_not_initialized() {
2909        // Arrange
2910        let producer = DefaultMQProducer {
2911            session: None,
2912            client_config: Default::default(),
2913            producer_config: Default::default(),
2914            default_mqproducer_impl: None,
2915        };
2916        let msg = Message::builder()
2917            .topic("test-topic")
2918            .body(Bytes::from_static(b"Hello world"))
2919            .build_unchecked();
2920        let callback = |_msg: Option<&SendResult>, _err: Option<&ClientError>| {
2921            // no-op
2922        };
2923        let mq = MessageQueue::new();
2924        let result: ClientResult<()> = producer
2925            .send_batch_to_queue_with_callback(vec![msg], mq, callback)
2926            .await;
2927        assert!(result.is_err());
2928        let err = result.unwrap_err();
2929        assert!(err.is(&rocketmq_error::CORE_LIFECYCLE_NOT_INITIALIZED));
2930    }
2931
2932    #[tokio::test]
2933    async fn recall_message_not_initialized() {
2934        // Arrange
2935        let producer = DefaultMQProducer {
2936            session: None,
2937            client_config: Default::default(),
2938            producer_config: Default::default(),
2939            default_mqproducer_impl: None,
2940        };
2941
2942        // Act
2943        let result = producer.recall_message("test-topic", "recall-handle-123").await;
2944
2945        // Assert
2946        assert!(result.is_err());
2947        let err = result.unwrap_err();
2948        assert!(err.is(&rocketmq_error::CORE_LIFECYCLE_NOT_INITIALIZED));
2949    }
2950
2951    #[test]
2952    fn trace_dispatcher_uses_configured_batch_num_like_java() {
2953        let mut client_config = ClientConfig::default();
2954        client_config.set_enable_trace(true);
2955        client_config.set_trace_msg_batch_num(7);
2956        let producer = DefaultMQProducer::builder(test_runtime())
2957            .client_config(client_config)
2958            .producer_group("producer_trace_batch_group")
2959            .build();
2960        let dispatcher = {
2961            let default_mqproducer_impl = producer
2962                .default_mqproducer_impl
2963                .as_ref()
2964                .expect("producer impl should exist");
2965            producer
2966                .prepare_trace_dispatcher(default_mqproducer_impl)
2967                .expect("trace dispatcher should be created")
2968        };
2969
2970        let async_dispatcher = dispatcher
2971            .as_any()
2972            .downcast_ref::<AsyncTraceDispatcher>()
2973            .expect("default trace dispatcher should be AsyncTraceDispatcher");
2974        assert_eq!(async_dispatcher.batch_num(), 7);
2975    }
2976
2977    #[test]
2978    fn producer_use_tls_facade_updates_impl_and_trace_dispatcher_like_java_client_config() {
2979        let mut producer = DefaultMQProducer::builder(test_runtime())
2980            .producer_group("producer_tls_group")
2981            .build();
2982        let dispatcher = Arc::new(AsyncTraceDispatcher::new(
2983            test_runtime(),
2984            "producer_tls_group",
2985            Type::Produce,
2986            1,
2987            "",
2988            None,
2989        ));
2990        producer.set_trace_dispatcher(dispatcher.clone());
2991
2992        assert!(!producer.is_use_tls());
2993        assert!(!dispatcher.is_use_tls());
2994        assert!(!producer
2995            .default_mqproducer_impl
2996            .as_ref()
2997            .expect("producer impl should exist")
2998            .is_use_tls());
2999
3000        producer.set_use_tls(true);
3001
3002        assert!(producer.is_use_tls());
3003        assert!(producer.client_config_snapshot().is_use_tls());
3004        assert!(dispatcher.is_use_tls());
3005        assert!(producer
3006            .default_mqproducer_impl
3007            .as_ref()
3008            .expect("producer impl should exist")
3009            .is_use_tls());
3010    }
3011
3012    #[test]
3013    fn producer_builder_use_tls_initializes_facade_and_impl_config() {
3014        let producer = DefaultMQProducer::builder(test_runtime())
3015            .producer_group("producer_tls_builder_group")
3016            .use_tls(true)
3017            .build();
3018
3019        assert!(producer.is_use_tls());
3020        assert!(producer
3021            .default_mqproducer_impl
3022            .as_ref()
3023            .expect("producer impl should exist")
3024            .is_use_tls());
3025    }
3026
3027    #[test]
3028    fn test_builder_with_batch_fields() {
3029        use crate::producer::default_mq_produce_builder::DefaultMQProducerBuilder;
3030
3031        let producer = DefaultMQProducerBuilder::new(test_runtime())
3032            .producer_group("test_group")
3033            .send_msg_max_timeout_per_request(5000)
3034            .batch_max_delay_ms(100)
3035            .batch_max_bytes(2 * 1024 * 1024)
3036            .total_batch_max_bytes(64 * 1024 * 1024)
3037            .build();
3038
3039        assert_eq!(producer.producer_group().to_string(), "test_group");
3040        assert_eq!(producer.send_msg_max_timeout_per_request(), Some(5000));
3041        assert_eq!(producer.batch_max_delay_ms(), Some(100));
3042        assert_eq!(producer.batch_max_bytes(), Some(2 * 1024 * 1024));
3043        assert_eq!(producer.total_batch_max_bytes(), Some(64 * 1024 * 1024));
3044    }
3045
3046    #[test]
3047    fn test_builder_default_batch_values() {
3048        use crate::producer::default_mq_produce_builder::DefaultMQProducerBuilder;
3049
3050        let producer = DefaultMQProducerBuilder::new(test_runtime())
3051            .producer_group("test_group")
3052            .build();
3053
3054        // Verify default values are None for batch fields
3055        assert_eq!(producer.send_msg_max_timeout_per_request(), None);
3056        assert_eq!(producer.batch_max_delay_ms(), None);
3057        assert_eq!(producer.batch_max_bytes(), None);
3058        assert_eq!(producer.total_batch_max_bytes(), None);
3059    }
3060
3061    fn assert_producer_compressor_matches_type(producer: &DefaultMQProducer, compression_type: CompressionType) {
3062        let body = b"rocketmq producer compressor parity";
3063        let compressed = producer
3064            .compressor()
3065            .expect("producer should have compressor")
3066            .compress(body, producer.compress_level())
3067            .expect("producer compressor should compress");
3068        let decompressed = compression_type
3069            .try_decompression(&compressed)
3070            .expect("matching compression type should decompress producer body");
3071
3072        assert_eq!(decompressed.as_ref(), body);
3073    }
3074
3075    #[test]
3076    fn producer_config_invalid_env_compress_type_falls_back_to_zlib_without_panic() {
3077        assert_eq!(
3078            ProducerConfig::parse_compression_type_or_zlib("snappy"),
3079            CompressionType::Zlib
3080        );
3081    }
3082
3083    #[test]
3084    fn set_compress_type_updates_compressor_like_java() {
3085        let mut producer = DefaultMQProducer::unbound();
3086
3087        producer.set_compress_type(CompressionType::LZ4);
3088
3089        assert_eq!(producer.compress_type(), CompressionType::LZ4);
3090        assert_producer_compressor_matches_type(&producer, CompressionType::LZ4);
3091    }
3092
3093    #[test]
3094    fn builder_compress_type_updates_compressor_like_java() {
3095        use crate::producer::default_mq_produce_builder::DefaultMQProducerBuilder;
3096
3097        let producer = DefaultMQProducerBuilder::new(test_runtime())
3098            .producer_group("test_group")
3099            .compress_type(CompressionType::Zstd)
3100            .build();
3101
3102        assert_eq!(producer.compress_type(), CompressionType::Zstd);
3103        assert_producer_compressor_matches_type(&producer, CompressionType::Zstd);
3104    }
3105
3106    #[test]
3107    fn produce_accumulator_inherits_preconfigured_batch_settings_like_java_init() {
3108        let mut producer = DefaultMQProducer::unbound();
3109        producer.set_batch_max_delay_ms(25);
3110        producer.set_batch_max_bytes(64 * 1024);
3111        producer.set_total_batch_max_bytes(8 * 1024 * 1024);
3112
3113        producer.set_produce_accumulator(ProduceAccumulator::new(
3114            crate::runtime::test_service_context("producer-accumulator-test"),
3115            "producer-accumulator",
3116        ));
3117
3118        let accumulator = producer
3119            .produce_accumulator()
3120            .expect("produce accumulator should be configured");
3121        assert_eq!(accumulator.batch_max_delay_ms(), 25);
3122        assert_eq!(accumulator.batch_max_bytes(), 64 * 1024);
3123        assert_eq!(accumulator.total_batch_max_bytes(), 8 * 1024 * 1024);
3124    }
3125
3126    #[test]
3127    fn batch_setting_updates_existing_produce_accumulator_like_java_runtime_setters() {
3128        let mut producer = DefaultMQProducer::unbound();
3129        producer.set_produce_accumulator(ProduceAccumulator::new(
3130            crate::runtime::test_service_context("producer-accumulator-test"),
3131            "producer-accumulator",
3132        ));
3133
3134        producer.set_batch_max_delay_ms(20);
3135        producer.set_batch_max_bytes(128 * 1024);
3136        producer.set_total_batch_max_bytes(16 * 1024 * 1024);
3137
3138        let accumulator = producer
3139            .produce_accumulator()
3140            .expect("produce accumulator should be configured");
3141        assert_eq!(accumulator.batch_max_delay_ms(), 20);
3142        assert_eq!(accumulator.batch_max_bytes(), 128 * 1024);
3143        assert_eq!(accumulator.total_batch_max_bytes(), 16 * 1024 * 1024);
3144    }
3145
3146    #[test]
3147    fn backpressure_runtime_setters_sync_impl_and_clamp_like_java() {
3148        let mut producer = DefaultMQProducer::builder(test_runtime())
3149            .producer_group("backpressure_group")
3150            .build();
3151
3152        producer.set_enable_backpressure_for_async_mode(true);
3153        producer.set_back_pressure_for_async_send_num(1);
3154        producer.set_back_pressure_for_async_send_size(128);
3155
3156        assert!(producer.enable_backpressure_for_async_mode());
3157        assert_eq!(
3158            producer.back_pressure_for_async_send_num(),
3159            MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM
3160        );
3161        assert_eq!(
3162            producer.get_back_pressure_for_async_send_num(),
3163            MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM
3164        );
3165        assert_eq!(
3166            producer.back_pressure_for_async_send_size(),
3167            MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE
3168        );
3169        assert_eq!(
3170            producer.get_back_pressure_for_async_send_size(),
3171            MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE
3172        );
3173
3174        let producer_impl = producer
3175            .default_mqproducer_impl
3176            .as_ref()
3177            .expect("producer impl should be initialized");
3178        assert!(producer_impl.enable_backpressure_for_async_mode());
3179        assert_eq!(
3180            producer_impl.back_pressure_for_async_send_num(),
3181            MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM
3182        );
3183        assert_eq!(
3184            producer_impl.back_pressure_for_async_send_size(),
3185            MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE
3186        );
3187    }
3188
3189    #[test]
3190    fn runtime_producer_config_setters_sync_impl_like_java_facade_reference() {
3191        let mut producer = DefaultMQProducer::builder(test_runtime())
3192            .producer_group("initial_group")
3193            .build();
3194
3195        producer.set_producer_group("updated_group");
3196        producer.set_send_msg_timeout(4321);
3197        producer.set_compress_msg_body_over_howmuch(8192);
3198        producer.set_max_message_size(16 * 1024 * 1024);
3199        producer.set_retry_times_when_send_failed(5);
3200        producer.set_retry_times_when_send_async_failed(6);
3201        producer.set_compress_type(CompressionType::LZ4);
3202        producer.set_compress_level(3);
3203        producer.add_retry_response_code(12_345);
3204
3205        assert_eq!(producer.get_send_msg_timeout(), 4321);
3206        assert_eq!(producer.get_compress_msg_body_over_howmuch(), 8192);
3207        assert_eq!(producer.get_max_message_size(), 16 * 1024 * 1024);
3208        assert_eq!(producer.get_retry_times_when_send_failed(), 5);
3209        assert_eq!(producer.get_retry_times_when_send_async_failed(), 6);
3210        assert_eq!(producer.get_compress_level(), 3);
3211
3212        let producer_impl = producer
3213            .default_mqproducer_impl
3214            .as_ref()
3215            .expect("producer impl should be initialized");
3216        let impl_config = producer_impl.producer_config();
3217
3218        assert_eq!(impl_config.producer_group(), "updated_group");
3219        assert_eq!(impl_config.send_msg_timeout(), 4321);
3220        assert_eq!(impl_config.retry_times_when_send_failed(), 5);
3221        assert_eq!(impl_config.compress_type(), CompressionType::LZ4);
3222        assert!(impl_config.compressor().is_some());
3223        assert!(producer.retry_response_codes().contains(&12_345));
3224        assert!(impl_config.retry_response_codes().contains(&12_345));
3225    }
3226
3227    #[test]
3228    fn producer_java_facade_accessors_sync_impl_without_panic() {
3229        let mut producer = DefaultMQProducer::builder(test_runtime())
3230            .producer_group("producer_java_facade_group")
3231            .build();
3232
3233        assert!(producer.default_mq_producer_impl().is_some());
3234
3235        producer.set_latency_max(vec![10, 20, 30]);
3236        producer.set_not_available_duration(vec![0, 100, 200]);
3237        producer.set_back_pressure_for_async_send_num_inside_adjust(1);
3238        producer.set_back_pressure_for_async_send_size_inside_adjust(128);
3239
3240        assert_eq!(producer.latency_max(), &[10, 20, 30]);
3241        assert_eq!(producer.not_available_duration(), &[0, 100, 200]);
3242        assert_eq!(
3243            producer.back_pressure_for_async_send_num(),
3244            MIN_BACK_PRESSURE_FOR_ASYNC_SEND_NUM
3245        );
3246        assert_eq!(
3247            producer.back_pressure_for_async_send_size(),
3248            MIN_BACK_PRESSURE_FOR_ASYNC_SEND_SIZE
3249        );
3250
3251        let producer_impl = producer
3252            .default_mq_producer_impl()
3253            .expect("producer impl should be initialized");
3254        let _impl_config = producer_impl.producer_config();
3255        assert_eq!(producer_impl.latency_max(), &[10, 20, 30]);
3256        assert_eq!(producer_impl.not_available_duration(), &[0, 100, 200]);
3257    }
3258
3259    #[test]
3260    fn test_producer_config_getters_setters_batch_fields() {
3261        let mut producer = DefaultMQProducer::unbound();
3262
3263        // Test send_msg_max_timeout_per_request
3264        producer.set_send_msg_max_timeout_per_request(3000);
3265        assert_eq!(producer.send_msg_max_timeout_per_request(), Some(3000));
3266
3267        producer.set_send_msg_max_timeout_per_request_option(None);
3268        assert_eq!(producer.send_msg_max_timeout_per_request(), None);
3269
3270        // Test batch_max_delay_ms
3271        producer.set_batch_max_delay_ms(50);
3272        assert_eq!(producer.batch_max_delay_ms(), Some(50));
3273
3274        producer.set_batch_max_delay_ms_option(None);
3275        assert_eq!(producer.batch_max_delay_ms(), None);
3276
3277        // Test batch_max_bytes
3278        producer.set_batch_max_bytes(4 * 1024 * 1024);
3279        assert_eq!(producer.batch_max_bytes(), Some(4 * 1024 * 1024));
3280
3281        producer.set_batch_max_bytes_option(None);
3282        assert_eq!(producer.batch_max_bytes(), None);
3283
3284        // Test total_batch_max_bytes
3285        producer.set_total_batch_max_bytes(128 * 1024 * 1024);
3286        assert_eq!(producer.total_batch_max_bytes(), Some(128 * 1024 * 1024));
3287
3288        producer.set_total_batch_max_bytes_option(None);
3289        assert_eq!(producer.total_batch_max_bytes(), None);
3290    }
3291
3292    #[test]
3293    fn test_producer_config_default_values_match_java() {
3294        let config = ProducerConfig::default();
3295
3296        // Verify default values match Java
3297        assert_eq!(config.back_pressure_for_async_send_num, 1024); // Java default
3298
3299        // Verify batch fields default to None
3300        assert_eq!(config.send_msg_max_timeout_per_request, None);
3301        assert_eq!(config.batch_max_delay_ms, None);
3302        assert_eq!(config.batch_max_bytes, None);
3303        assert_eq!(config.total_batch_max_bytes, None);
3304    }
3305}