11using System . Collections . Concurrent ;
2+ using System . Globalization ;
23using NewLife . Log ;
34using NewLife . Reflection ;
45using NewLife . RocketMQ . Client ;
@@ -12,6 +13,8 @@ namespace NewLife.RocketMQ;
1213/// <summary>生产者</summary>
1314public class Producer : MqBase
1415{
16+ private const Int32 CommitLogOffsetHexLength = 16 ;
17+
1518 #region 属性
1619 /// <summary>负载均衡。发布消息时,分发到各个队列的负载均衡算法,默认使用带权重的轮询</summary>
1720 public ILoadBalance LoadBalance { get ; set ; }
@@ -229,6 +232,36 @@ public virtual SendResult Publish(Object body, String tags, String keys, Int32 t
229232
230233 return Publish ( message , null , timeout ) ;
231234 }
235+
236+ /// <summary>发布事务消息(半消息)</summary>
237+ /// <param name="message">消息体</param>
238+ /// <param name="queue">目标队列</param>
239+ /// <param name="timeout"></param>
240+ /// <returns></returns>
241+ public virtual SendResult PublishTransaction ( Message message , MessageQueue queue = null , Int32 timeout = - 1 )
242+ {
243+ if ( message is null ) throw new ArgumentNullException ( nameof ( message ) ) ;
244+
245+ message . Properties [ "TRAN_MSG" ] = "true" ;
246+ message . Properties [ "PGROUP" ] = Group ;
247+
248+ return Publish ( message , queue , timeout ) ;
249+ }
250+
251+ /// <summary>发布事务消息(半消息)</summary>
252+ /// <param name="body"></param>
253+ /// <param name="tags"></param>
254+ /// <param name="keys"></param>
255+ /// <param name="timeout"></param>
256+ /// <returns></returns>
257+ public virtual SendResult PublishTransaction ( Object body , String tags = null , String keys = null , Int32 timeout = - 1 )
258+ {
259+ var message = CreateMessage ( body ) ;
260+ message . Tags = tags ;
261+ message . Keys = keys ;
262+
263+ return PublishTransaction ( message , null , timeout ) ;
264+ }
232265 #endregion
233266
234267 #region 异步发布消息
@@ -319,6 +352,21 @@ public virtual async Task<SendResult> PublishAsync(Message message, MessageQueue
319352 return null ;
320353 }
321354
355+ /// <summary>异步发布事务消息(半消息)</summary>
356+ /// <param name="message">消息体</param>
357+ /// <param name="queue">目标队列</param>
358+ /// <param name="cancellationToken">取消令牌</param>
359+ /// <returns></returns>
360+ public virtual Task < SendResult > PublishTransactionAsync ( Message message , MessageQueue queue = null , CancellationToken cancellationToken = default )
361+ {
362+ if ( message is null ) throw new ArgumentNullException ( nameof ( message ) ) ;
363+
364+ message . Properties [ "TRAN_MSG" ] = "true" ;
365+ message . Properties [ "PGROUP" ] = Group ;
366+
367+ return PublishAsync ( message , queue , cancellationToken ) ;
368+ }
369+
322370 /// <summary>发布消息</summary>
323371 /// <param name="body"></param>
324372 /// <returns></returns>
@@ -554,6 +602,60 @@ public virtual void PublishDelay(Object body, DelayTimeLevels level, String tags
554602 }
555603 #endregion
556604
605+ #region 结束事务消息
606+ /// <summary>结束事务消息。提交或回滚事务</summary>
607+ /// <param name="result">发布事务消息返回结果</param>
608+ /// <param name="state">事务状态</param>
609+ /// <param name="fromTransactionCheck">是否来自事务回查</param>
610+ public virtual void EndTransaction ( SendResult result , TransactionState state , Boolean fromTransactionCheck = false )
611+ {
612+ if ( result is null ) throw new ArgumentNullException ( nameof ( result ) ) ;
613+ if ( result . Queue == null ) throw new ArgumentNullException ( nameof ( result ) , "缺少队列信息" ) ;
614+ if ( result . Queue . BrokerName . IsNullOrEmpty ( ) ) throw new ArgumentNullException ( nameof ( result ) , "缺少BrokerName" ) ;
615+
616+ var header = new EndTransactionRequestHeader
617+ {
618+ ProducerGroup = Group ,
619+ TranStateTableOffset = result . QueueOffset ,
620+ CommitLogOffset = GetCommitLogOffset ( result . OffsetMsgId ) ,
621+ CommitOrRollback = ( Int32 ) state ,
622+ FromTransactionCheck = fromTransactionCheck ,
623+ MsgId = result . MsgId ,
624+ TransactionId = result . TransactionId ,
625+ } ;
626+
627+ var bk = GetBroker ( result . Queue . BrokerName ) ;
628+ bk . Invoke ( RequestCode . END_TRANSACTION , null , header . GetProperties ( ) ) ;
629+ }
630+
631+ /// <summary>异步结束事务消息。提交或回滚事务</summary>
632+ /// <param name="result">发布事务消息返回结果</param>
633+ /// <param name="state">事务状态</param>
634+ /// <param name="fromTransactionCheck">是否来自事务回查</param>
635+ /// <param name="cancellationToken">取消令牌</param>
636+ /// <returns></returns>
637+ public virtual async Task EndTransactionAsync ( SendResult result , TransactionState state , Boolean fromTransactionCheck = false , CancellationToken cancellationToken = default )
638+ {
639+ if ( result is null ) throw new ArgumentNullException ( nameof ( result ) ) ;
640+ if ( result . Queue == null ) throw new ArgumentNullException ( nameof ( result ) , "缺少队列信息" ) ;
641+ if ( result . Queue . BrokerName . IsNullOrEmpty ( ) ) throw new ArgumentNullException ( nameof ( result ) , "缺少BrokerName" ) ;
642+
643+ var header = new EndTransactionRequestHeader
644+ {
645+ ProducerGroup = Group ,
646+ TranStateTableOffset = result . QueueOffset ,
647+ CommitLogOffset = GetCommitLogOffset ( result . OffsetMsgId ) ,
648+ CommitOrRollback = ( Int32 ) state ,
649+ FromTransactionCheck = fromTransactionCheck ,
650+ MsgId = result . MsgId ,
651+ TransactionId = result . TransactionId ,
652+ } ;
653+
654+ var bk = GetBroker ( result . Queue . BrokerName ) ;
655+ await bk . InvokeAsync ( RequestCode . END_TRANSACTION , null , header . GetProperties ( ) , false , cancellationToken ) . ConfigureAwait ( false ) ;
656+ }
657+ #endregion
658+
557659 #region 辅助
558660 /// <summary>
559661 /// 创建消息,设计于支持用户重载以改变消息序列化行为
@@ -594,8 +696,18 @@ private SendMessageRequestHeader CreateHeader(Message message)
594696 DefaultTopicQueueNums = DefaultTopicQueueNums
595697 } ;
596698
699+ if ( message . Properties . TryGetValue ( "TRAN_MSG" , out var str ) && str . ToBoolean ( ) ) smrh . SysFlag = ( Int32 ) TransactionState . Prepared ;
700+
597701 return smrh ;
598702 }
703+
704+ private static Int64 GetCommitLogOffset ( String offsetMsgId )
705+ {
706+ if ( offsetMsgId . IsNullOrEmpty ( ) || offsetMsgId . Length < CommitLogOffsetHexLength ) return 0 ;
707+
708+ // OffsetMsgId尾部16位是8字节(Int64)的CommitLogOffset十六进制表示
709+ return Int64 . TryParse ( offsetMsgId . Substring ( offsetMsgId . Length - CommitLogOffsetHexLength ) , NumberStyles . HexNumber , CultureInfo . InvariantCulture , out var rs ) ? rs : 0 ;
710+ }
599711 #endregion
600712
601713 #region 选择Broker队列
@@ -752,4 +864,4 @@ internal void HandleReplyMessage(MessageExt message)
752864 }
753865 }
754866 #endregion
755- }
867+ }
0 commit comments