1use std::any::Any;
16use std::collections::HashMap;
17use std::sync::Arc;
18
19use crate::ClientError;
20use cheetah_string::CheetahString;
21use rocketmq_model::common::message::message_ext::MessageExt;
22use rocketmq_model::common::message::message_queue::MessageQueue;
23use rocketmq_model::common::message::MessageTrait;
24
25use crate::base::query_result::QueryResult;
26use crate::producer::default_mq_producer::DefaultMQProducer;
27use crate::producer::producer_backend::ProducerBackend;
28use crate::producer::send_callback::ArcSendCallback;
29use crate::producer::send_result::SendResult;
30use crate::producer::transaction_listener::ArcTransactionListener;
31use crate::producer::transaction_listener::TransactionListener;
32use crate::producer::transaction_mq_produce_builder::TransactionMQProducerBuilder;
33use crate::producer::transaction_send_result::TransactionSendResult;
34use crate::runtime::ClientRuntime;
35use crate::session::ClientSession;
36use crate::session::ClientSessionProvider;
37
38#[derive(Clone)]
42pub struct TransactionProducerConfig {
43 pub transaction_listener: Option<ArcTransactionListener>,
45
46 pub transaction_check_listener: Option<ArcTransactionListener>,
48
49 pub check_thread_pool_min_size: u32,
53
54 pub check_thread_pool_max_size: u32,
58
59 pub check_request_hold_max: u32,
65}
66
67impl Default for TransactionProducerConfig {
68 fn default() -> Self {
69 Self {
70 transaction_listener: None,
71 transaction_check_listener: None,
72 check_thread_pool_min_size: 1,
73 check_thread_pool_max_size: 1,
74 check_request_hold_max: 2000,
75 }
76 }
77}
78
79pub struct TransactionMQProducer {
80 default_producer: DefaultMQProducer,
81 transaction_producer_config: TransactionProducerConfig,
82}
83
84impl TransactionMQProducer {
85 pub fn builder(client_runtime: Arc<ClientRuntime>) -> TransactionMQProducerBuilder {
86 TransactionMQProducerBuilder::new(client_runtime)
87 }
88
89 #[must_use]
90 pub fn client_session(&self) -> Option<&ClientSession> {
91 self.default_producer.client_session()
92 }
93
94 pub(crate) fn new(
95 transaction_producer_config: TransactionProducerConfig,
96 default_producer: DefaultMQProducer,
97 ) -> Self {
98 Self {
99 default_producer,
100 transaction_producer_config,
101 }
102 }
103
104 pub(crate) fn default_producer_mut(&mut self) -> &mut DefaultMQProducer {
105 &mut self.default_producer
106 }
107
108 pub async fn start(&mut self) -> crate::ClientResult<()> {
109 <Self as ProducerBackend>::start(self).await
110 }
111
112 pub async fn shutdown(&mut self) {
113 <Self as ProducerBackend>::shutdown(self).await;
114 }
115
116 pub async fn send_message_in_transaction<T, M>(
117 &self,
118 msg: M,
119 arg: Option<T>,
120 ) -> crate::ClientResult<TransactionSendResult>
121 where
122 T: std::any::Any + Sync + Send,
123 M: MessageTrait + Send + Sync,
124 {
125 <Self as ProducerBackend>::send_message_in_transaction(self, msg, arg).await
126 }
127
128 pub fn set_transaction_listener(&mut self, transaction_listener: impl TransactionListener) {
129 self.set_transaction_listener_arc(Arc::new(transaction_listener));
130 }
131
132 pub fn transaction_listener(&self) -> Option<ArcTransactionListener> {
133 self.transaction_producer_config.transaction_listener.clone()
134 }
135
136 pub fn get_transaction_listener(&self) -> Option<ArcTransactionListener> {
137 self.transaction_listener()
138 }
139
140 pub fn transaction_check_listener(&self) -> Option<ArcTransactionListener> {
141 self.transaction_producer_config.transaction_check_listener.clone()
142 }
143
144 pub fn get_transaction_check_listener(&self) -> Option<ArcTransactionListener> {
145 self.transaction_check_listener()
146 }
147
148 pub fn set_transaction_check_listener(&mut self, transaction_check_listener: impl TransactionListener) {
149 self.set_transaction_check_listener_arc(Arc::new(transaction_check_listener));
150 }
151
152 pub fn set_transaction_check_listener_arc(&mut self, transaction_check_listener: ArcTransactionListener) {
153 self.transaction_producer_config.transaction_check_listener = Some(transaction_check_listener);
154 }
155
156 pub fn set_transaction_listener_arc(&mut self, transaction_listener: ArcTransactionListener) {
157 self.transaction_producer_config.transaction_listener = Some(transaction_listener.clone());
158 if let Some(default_mqproducer_impl) = self.default_producer.default_mqproducer_impl.as_ref() {
159 default_mqproducer_impl.set_transaction_listener(transaction_listener);
160 } else {
161 tracing::warn!("DefaultMQProducerImpl is not initialized; transaction listener stored in config");
162 }
163 }
164
165 pub fn check_thread_pool_min_size(&self) -> u32 {
166 self.transaction_producer_config.check_thread_pool_min_size
167 }
168
169 pub fn get_check_thread_pool_min_size(&self) -> u32 {
170 self.check_thread_pool_min_size()
171 }
172
173 pub fn set_check_thread_pool_min_size(&mut self, check_thread_pool_min_size: u32) {
174 self.transaction_producer_config.check_thread_pool_min_size = check_thread_pool_min_size;
175 }
176
177 pub fn check_thread_pool_max_size(&self) -> u32 {
178 self.transaction_producer_config.check_thread_pool_max_size
179 }
180
181 pub fn get_check_thread_pool_max_size(&self) -> u32 {
182 self.check_thread_pool_max_size()
183 }
184
185 pub fn set_check_thread_pool_max_size(&mut self, check_thread_pool_max_size: u32) {
186 self.transaction_producer_config.check_thread_pool_max_size = check_thread_pool_max_size;
187 }
188
189 pub fn check_request_hold_max(&self) -> u32 {
190 self.transaction_producer_config.check_request_hold_max
191 }
192
193 pub fn get_check_request_hold_max(&self) -> u32 {
194 self.check_request_hold_max()
195 }
196
197 pub fn set_check_request_hold_max(&mut self, check_request_hold_max: u32) {
198 self.transaction_producer_config.check_request_hold_max = check_request_hold_max;
199 }
200
201 #[inline]
202 pub fn is_use_tls(&self) -> bool {
203 self.default_producer.is_use_tls()
204 }
205
206 #[inline]
207 pub fn set_use_tls(&mut self, use_tls: bool) {
208 self.default_producer.set_use_tls(use_tls);
209 }
210}
211
212impl ClientSessionProvider for TransactionMQProducer {
213 fn client_session(&self) -> Option<&ClientSession> {
214 self.default_producer.client_session()
215 }
216}
217
218impl ProducerBackend for TransactionMQProducer {
219 async fn start(&mut self) -> crate::ClientResult<()> {
220 let transaction_listener = self.transaction_producer_config.transaction_listener.clone();
221 let default_mqproducer_impl = self
222 .default_producer
223 .default_mqproducer_impl
224 .as_ref()
225 .ok_or(ClientError::not_initialized("DefaultMQProducerImpl is not initialized"))?;
226 if let Some(transaction_listener) = transaction_listener {
227 default_mqproducer_impl.set_transaction_listener(transaction_listener);
228 }
229 default_mqproducer_impl.init_transaction_env(
230 self.transaction_producer_config.check_thread_pool_min_size,
231 self.transaction_producer_config.check_thread_pool_max_size,
232 self.transaction_producer_config.check_request_hold_max,
233 )?;
234 self.default_producer.start().await
235 }
236
237 async fn shutdown(&mut self) {
238 self.default_producer.shutdown().await;
239 if let Some(default_mqproducer_impl) = self.default_producer.default_mqproducer_impl.as_ref() {
240 default_mqproducer_impl.destroy_transaction_env().await;
241 }
242 }
243
244 async fn fetch_publish_message_queues(&mut self, topic: &str) -> crate::ClientResult<Vec<MessageQueue>> {
245 self.default_producer.fetch_publish_message_queues(topic).await
246 }
247
248 async fn create_topic(
249 &mut self,
250 key: &str,
251 new_topic: &str,
252 queue_num: i32,
253 attributes: HashMap<String, String>,
254 ) -> crate::ClientResult<()> {
255 self.default_producer
256 .create_topic(key, new_topic, queue_num, attributes)
257 .await
258 }
259
260 async fn create_topic_with_flag(
261 &mut self,
262 key: &str,
263 new_topic: &str,
264 queue_num: i32,
265 topic_sys_flag: i32,
266 attributes: HashMap<String, String>,
267 ) -> crate::ClientResult<()> {
268 self.default_producer
269 .create_topic_with_flag(key, new_topic, queue_num, topic_sys_flag, attributes)
270 .await
271 }
272
273 async fn search_offset(&mut self, mq: &MessageQueue, timestamp: u64) -> crate::ClientResult<i64> {
274 self.default_producer.search_offset(mq, timestamp).await
275 }
276
277 async fn max_offset(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
278 self.default_producer.max_offset(mq).await
279 }
280
281 async fn min_offset(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
282 self.default_producer.min_offset(mq).await
283 }
284
285 async fn earliest_msg_store_time(&mut self, mq: &MessageQueue) -> crate::ClientResult<i64> {
286 self.default_producer.earliest_msg_store_time(mq).await
287 }
288
289 async fn query_message(
290 &mut self,
291 topic: &str,
292 key: &str,
293 max_num: i32,
294 begin: u64,
295 end: u64,
296 ) -> crate::ClientResult<QueryResult> {
297 self.default_producer
298 .query_message(topic, key, max_num, begin, end)
299 .await
300 }
301
302 async fn view_message(&mut self, topic: &str, msg_id: &str) -> crate::ClientResult<MessageExt> {
303 self.default_producer.view_message(topic, msg_id).await
304 }
305
306 async fn send<M>(&self, msg: M) -> crate::ClientResult<Option<SendResult>>
307 where
308 M: MessageTrait + Send + Sync,
309 {
310 self.default_producer.send(msg).await
311 }
312
313 async fn send_with_timeout<M>(&self, msg: M, timeout: u64) -> crate::ClientResult<Option<SendResult>>
314 where
315 M: MessageTrait + Send + Sync,
316 {
317 self.default_producer.send_with_timeout(msg, timeout).await
318 }
319
320 async fn send_with_callback<M, F>(&self, msg: M, send_callback: F) -> crate::ClientResult<()>
321 where
322 M: MessageTrait + Send + Sync,
323 F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
324 {
325 self.default_producer.send_with_callback(msg, send_callback).await
326 }
327
328 async fn send_with_callback_timeout<F, M>(&self, msg: M, send_callback: F, timeout: u64) -> crate::ClientResult<()>
329 where
330 F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
331 M: MessageTrait + Send + Sync,
332 {
333 self.default_producer
334 .send_with_callback_timeout(msg, send_callback, timeout)
335 .await
336 }
337
338 async fn send_oneway<M>(&self, msg: M) -> crate::ClientResult<()>
339 where
340 M: MessageTrait + Send + Sync,
341 {
342 self.default_producer.send_oneway(msg).await
343 }
344
345 async fn send_to_queue<M>(&self, msg: M, mq: MessageQueue) -> crate::ClientResult<Option<SendResult>>
346 where
347 M: MessageTrait + Send + Sync,
348 {
349 self.default_producer.send_to_queue(msg, mq).await
350 }
351
352 async fn send_to_queue_with_timeout<M>(
353 &self,
354 msg: M,
355 mq: MessageQueue,
356 timeout: u64,
357 ) -> crate::ClientResult<Option<SendResult>>
358 where
359 M: MessageTrait + Send + Sync,
360 {
361 self.default_producer.send_to_queue_with_timeout(msg, mq, timeout).await
362 }
363
364 async fn send_to_queue_with_callback<M, F>(
365 &self,
366 msg: M,
367 mq: MessageQueue,
368 send_callback: F,
369 ) -> crate::ClientResult<()>
370 where
371 M: MessageTrait + Send + Sync,
372 F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
373 {
374 self.default_producer
375 .send_to_queue_with_callback(msg, mq, send_callback)
376 .await
377 }
378
379 async fn send_to_queue_with_callback_timeout<M, F>(
380 &self,
381 msg: M,
382 mq: MessageQueue,
383 send_callback: F,
384 timeout: u64,
385 ) -> crate::ClientResult<()>
386 where
387 M: MessageTrait + Send + Sync,
388 F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
389 {
390 self.default_producer
391 .send_to_queue_with_callback_timeout(msg, mq, send_callback, timeout)
392 .await
393 }
394
395 async fn send_oneway_to_queue<M>(&self, msg: M, mq: MessageQueue) -> crate::ClientResult<()>
396 where
397 M: MessageTrait + Send + Sync,
398 {
399 self.default_producer.send_oneway_to_queue(msg, mq).await
400 }
401
402 async fn send_with_selector<M, S, T>(&self, msg: M, selector: S, arg: T) -> crate::ClientResult<Option<SendResult>>
403 where
404 M: MessageTrait + Send + Sync,
405 S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
406 T: Send + Sync,
407 {
408 self.default_producer.send_with_selector(msg, selector, arg).await
409 }
410
411 async fn send_with_selector_timeout<M, S, T>(
412 &self,
413 msg: M,
414 selector: S,
415 arg: T,
416 timeout: u64,
417 ) -> crate::ClientResult<Option<SendResult>>
418 where
419 M: MessageTrait + Send + Sync,
420 S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
421 T: Send + Sync,
422 {
423 self.default_producer
424 .send_with_selector_timeout(msg, selector, arg, timeout)
425 .await
426 }
427
428 async fn send_with_selector_callback<M, S, T>(
429 &self,
430 msg: M,
431 selector: S,
432 arg: T,
433 send_callback: Option<ArcSendCallback>,
434 ) -> crate::ClientResult<()>
435 where
436 M: MessageTrait + Send + Sync,
437 S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync,
438 T: Send + Sync,
439 {
440 self.default_producer
441 .send_with_selector_callback(msg, selector, arg, send_callback)
442 .await
443 }
444
445 async fn send_with_selector_callback_timeout<M, S, T>(
446 &self,
447 msg: M,
448 selector: S,
449 arg: T,
450 send_callback: Option<ArcSendCallback>,
451 timeout: u64,
452 ) -> crate::ClientResult<()>
453 where
454 M: MessageTrait + Send + Sync,
455 S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
456 T: Send + Sync + 'static,
457 {
458 self.default_producer
459 .send_with_selector_callback_timeout(msg, selector, arg, send_callback, timeout)
460 .await
461 }
462
463 async fn send_oneway_with_selector<M, S, T>(&self, msg: M, selector: S, arg: T) -> crate::ClientResult<()>
464 where
465 M: MessageTrait + Send + Sync,
466 S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
467 T: Send + Sync + 'static,
468 {
469 self.default_producer
470 .send_oneway_with_selector(msg, selector, arg)
471 .await
472 }
473
474 async fn send_message_in_transaction<T, M>(
475 &self,
476 mut msg: M,
477 arg: Option<T>,
478 ) -> crate::ClientResult<TransactionSendResult>
479 where
480 T: std::any::Any + Sync + Send,
481 M: MessageTrait + Send + Sync,
482 {
483 let transaction_listener = self
484 .transaction_producer_config
485 .transaction_listener
486 .clone()
487 .ok_or_else(|| crate::mq_client_err!("TransactionListener is null"))?;
488
489 msg.set_topic(self.default_producer.with_namespace(msg.topic()));
490 let default_mqproducer_impl =
491 self.default_producer
492 .default_mqproducer_impl
493 .as_ref()
494 .ok_or(crate::ClientError::not_initialized(
495 "DefaultMQProducerImpl is not initialized",
496 ))?;
497 default_mqproducer_impl.set_transaction_listener(transaction_listener);
498 default_mqproducer_impl
499 .send_message_in_transaction(msg, arg.map(|x| Box::new(x) as Box<dyn Any + Sync + Send>))
500 .await
501 }
502
503 async fn send_batch<M>(&self, msgs: Vec<M>) -> crate::ClientResult<SendResult>
504 where
505 M: MessageTrait + Send + Sync,
506 {
507 self.default_producer.send_batch(msgs).await
508 }
509
510 async fn send_batch_with_timeout<M>(&self, msgs: Vec<M>, timeout: u64) -> crate::ClientResult<SendResult>
511 where
512 M: MessageTrait + Send + Sync,
513 {
514 self.default_producer.send_batch_with_timeout(msgs, timeout).await
515 }
516
517 async fn send_batch_to_queue<M>(&self, msgs: Vec<M>, mq: MessageQueue) -> crate::ClientResult<SendResult>
518 where
519 M: MessageTrait + Send + Sync,
520 {
521 self.default_producer.send_batch_to_queue(msgs, mq).await
522 }
523
524 async fn send_batch_to_queue_with_timeout<M>(
525 &self,
526 msgs: Vec<M>,
527 mq: MessageQueue,
528 timeout: u64,
529 ) -> crate::ClientResult<SendResult>
530 where
531 M: MessageTrait + Send + Sync,
532 {
533 self.default_producer
534 .send_batch_to_queue_with_timeout(msgs, mq, timeout)
535 .await
536 }
537
538 async fn send_batch_with_callback<M, F>(&self, msgs: Vec<M>, f: F) -> crate::ClientResult<()>
539 where
540 M: MessageTrait + Send + Sync,
541 F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
542 {
543 self.default_producer.send_batch_with_callback(msgs, f).await
544 }
545
546 async fn send_batch_with_callback_timeout<M, F>(&self, msgs: Vec<M>, f: F, timeout: u64) -> crate::ClientResult<()>
547 where
548 M: MessageTrait + Send + Sync,
549 F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
550 {
551 self.default_producer
552 .send_batch_with_callback_timeout(msgs, f, timeout)
553 .await
554 }
555
556 async fn send_batch_to_queue_with_callback<M, F>(
557 &self,
558 msgs: Vec<M>,
559 mq: MessageQueue,
560 f: F,
561 ) -> crate::ClientResult<()>
562 where
563 M: MessageTrait + Send + Sync,
564 F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
565 {
566 self.default_producer
567 .send_batch_to_queue_with_callback(msgs, mq, f)
568 .await
569 }
570
571 async fn send_batch_to_queue_with_callback_timeout<M, F>(
572 &self,
573 msgs: Vec<M>,
574 mq: MessageQueue,
575 f: F,
576 timeout: u64,
577 ) -> crate::ClientResult<()>
578 where
579 M: MessageTrait + Send + Sync,
580 F: Fn(Option<&SendResult>, Option<&ClientError>) + Send + Sync + 'static,
581 {
582 self.default_producer
583 .send_batch_to_queue_with_callback_timeout(msgs, mq, f, timeout)
584 .await
585 }
586
587 async fn request<M>(&self, msg: M, timeout: u64) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
588 where
589 M: MessageTrait + Send + Sync,
590 {
591 self.default_producer.request(msg, timeout).await
592 }
593
594 async fn request_with_callback<F, M>(&self, msg: M, request_callback: F, timeout: u64) -> crate::ClientResult<()>
595 where
596 F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
597 M: MessageTrait + Send + Sync,
598 {
599 self.default_producer
600 .request_with_callback(msg, request_callback, timeout)
601 .await
602 }
603
604 async fn request_with_selector<M, S, T>(
605 &self,
606 msg: M,
607 selector: S,
608 arg: T,
609 timeout: u64,
610 ) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
611 where
612 S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
613 T: Send + Sync + 'static,
614 M: MessageTrait + Send + Sync,
615 {
616 self.default_producer
617 .request_with_selector(msg, selector, arg, timeout)
618 .await
619 }
620
621 async fn request_with_selector_callback<M, S, T, F>(
622 &self,
623 msg: M,
624 selector: S,
625 arg: T,
626 request_callback: F,
627 timeout: u64,
628 ) -> crate::ClientResult<()>
629 where
630 S: Fn(&[MessageQueue], &M, &T) -> Option<MessageQueue> + Send + Sync + 'static,
631 F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
632 T: Send + Sync + 'static,
633 M: MessageTrait + Send + Sync,
634 {
635 self.default_producer
636 .request_with_selector_callback(msg, selector, arg, request_callback, timeout)
637 .await
638 }
639
640 async fn request_to_queue<M>(
641 &self,
642 msg: M,
643 mq: MessageQueue,
644 timeout: u64,
645 ) -> crate::ClientResult<Box<dyn MessageTrait + Send>>
646 where
647 M: MessageTrait + Send + Sync,
648 {
649 self.default_producer.request_to_queue(msg, mq, timeout).await
650 }
651
652 async fn request_to_queue_with_callback<M, F>(
653 &self,
654 msg: M,
655 mq: MessageQueue,
656 request_callback: F,
657 timeout: u64,
658 ) -> crate::ClientResult<()>
659 where
660 F: Fn(Option<&dyn MessageTrait>, Option<&crate::ClientError>) + Send + Sync + 'static,
661 M: MessageTrait + Send + Sync,
662 {
663 self.default_producer
664 .request_to_queue_with_callback(msg, mq, request_callback, timeout)
665 .await
666 }
667
668 async fn recall_message(
669 &self,
670 topic: impl Into<CheetahString>,
671 recall_handle: impl Into<CheetahString>,
672 ) -> crate::ClientResult<String> {
673 self.default_producer.recall_message(topic, recall_handle).await
674 }
675
676 fn as_any(&self) -> &dyn Any {
677 self
678 }
679
680 fn as_any_mut(&mut self) -> &mut dyn Any {
681 self
682 }
683}
684
685#[cfg(test)]
686mod tests {
687 use super::*;
688
689 #[test]
690 fn java_getter_aliases_delegate_to_transaction_config() {
691 let producer =
692 TransactionMQProducer::builder(crate::runtime::test_client_runtime("transaction-producer-getter-test"))
693 .build();
694
695 assert!(producer.get_transaction_listener().is_none());
696 }
697
698 #[test]
699 fn use_tls_facade_and_builder_delegate_to_default_producer_like_java_client_config() {
700 let mut producer =
701 TransactionMQProducer::builder(crate::runtime::test_client_runtime("transaction-producer-test"))
702 .producer_group("transaction_tls_group")
703 .use_tls(true)
704 .build();
705
706 assert!(producer.is_use_tls());
707 assert!(producer.default_producer.is_use_tls());
708 assert!(producer
709 .default_producer
710 .default_mqproducer_impl
711 .as_ref()
712 .expect("producer impl should exist")
713 .is_use_tls());
714
715 producer.set_use_tls(false);
716
717 assert!(!producer.is_use_tls());
718 assert!(!producer.default_producer.is_use_tls());
719 assert!(!producer
720 .default_producer
721 .default_mqproducer_impl
722 .as_ref()
723 .expect("producer impl should exist")
724 .is_use_tls());
725 }
726}