1use 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
67struct 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: CheetahString,
121 topics: Vec<CheetahString>,
123 create_topic_key: CheetahString,
124 default_topic_queue_nums: u32,
126 send_msg_timeout: u32,
128 send_msg_max_timeout_per_request: Option<u32>,
131 compress_msg_body_over_howmuch: u32,
134 retry_times_when_send_failed: u32,
138 retry_times_when_send_async_failed: u32,
142 retry_another_broker_when_not_store_ok: bool,
144 max_message_size: u32,
146 trace_dispatcher: Option<ArcTraceDispatcher>,
147 auto_batch: bool,
149 batch_max_delay_ms: Option<u32>,
152 batch_max_bytes: Option<u64>,
155 total_batch_max_bytes: Option<u64>,
158 produce_accumulator: Option<Arc<ProduceAccumulator>>,
160 enable_backpressure_for_async_mode: bool,
162 back_pressure_for_async_send_num: u32,
165 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 #[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 #[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 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 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 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 if msg.topic().starts_with(mix_all::RETRY_GROUP_TOPIC_PREFIX) {
1604 return false;
1605 }
1606 if msg.get_properties().contains_key(MessageConst::PROPERTY_PRODUCER_GROUP) {
1608 return false;
1609 }
1610 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 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 };
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 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 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 };
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 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 };
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 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 };
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 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 };
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 let producer = DefaultMQProducer {
2936 session: None,
2937 client_config: Default::default(),
2938 producer_config: Default::default(),
2939 default_mqproducer_impl: None,
2940 };
2941
2942 let result = producer.recall_message("test-topic", "recall-handle-123").await;
2944
2945 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 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 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 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 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 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 assert_eq!(config.back_pressure_for_async_send_num, 1024); 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}