TmcApiClient.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. using System;
  2. using System.Diagnostics;
  3. using System.Threading;
  4. using Top.Api;
  5. using Top.Api.Domain;
  6. using Top.Api.Request;
  7. namespace Top.Tmc
  8. {
  9. public class TmcApiClient
  10. {
  11. private ITopClient _topClient;
  12. private readonly string _appkey;
  13. private readonly string _appSecret;
  14. private readonly string _groupName;
  15. /**
  16. * 每次调用api拉取的消息数量
  17. */
  18. private int _quality;
  19. /**
  20. * 得到消息为空时,下次拉取的等待间隔
  21. * 每次消费得到的消息为空时, 至少暂停1s再去执行下一次循环拉消息
  22. */
  23. private int _duration;
  24. private volatile bool _running;
  25. public event EventHandler<MessageArgs> OnMessage;
  26. /**
  27. * 循环拉取消息线程数量
  28. */
  29. private int _pullRequestThreads;
  30. private bool EnableTraceLog { get; set; }
  31. private ITopLogger Logger { get; set; }
  32. public int Quality
  33. {
  34. get => _quality;
  35. set => _quality = Math.Max(1, value);
  36. }
  37. public int Duration
  38. {
  39. get => _duration;
  40. set => _duration = Math.Max(1, value);
  41. }
  42. public int PullRequestThreads
  43. {
  44. get => _pullRequestThreads;
  45. set => _pullRequestThreads = Math.Max(1, value);
  46. }
  47. public TmcApiClient(string appkey, string appSecret, string groupName)
  48. {
  49. Logger = Log.Instance;
  50. _appkey = appkey;
  51. _appSecret = appSecret;
  52. _groupName = groupName;
  53. _quality = 20;
  54. _duration = 5;
  55. _pullRequestThreads = 1;
  56. _running = false;
  57. _topClient = null;
  58. }
  59. public void Connect(string uri)
  60. {
  61. Console.WriteLine("TmcApiClient Start");
  62. _topClient = new DefaultTopClient(uri, _appkey, _appSecret, "json");
  63. _running = true;
  64. for (var i = 0; i < _pullRequestThreads; i++)
  65. {
  66. var thread = new Thread(o =>
  67. {
  68. while (_running)
  69. {
  70. try
  71. {
  72. var req = new TmcMessagesConsumeRequest
  73. {
  74. GroupName = _groupName,
  75. Quantity = _quality
  76. };
  77. var sw = new Stopwatch();
  78. sw.Start();
  79. var rsp = _topClient.Execute(req);
  80. sw.Stop();
  81. Console.WriteLine("request time: " + sw.ElapsedMilliseconds);
  82. if (rsp == null || rsp.Messages == null || rsp.Messages.Count < 1)
  83. {
  84. Console.WriteLine("wait...");
  85. Thread.Sleep(new TimeSpan(0, 0, _duration));
  86. }
  87. else
  88. {
  89. Console.WriteLine(rsp.Messages.Count);
  90. foreach (var msg in rsp.Messages)
  91. {
  92. HandleMessage(msg);
  93. }
  94. }
  95. }
  96. catch (Exception ex)
  97. {
  98. Logger.Warn($"pull message exception, error: {ex}");
  99. }
  100. }
  101. })
  102. {
  103. IsBackground = true,
  104. Name = $"TmcApiClient PullRequestThread-{i}"
  105. };
  106. Console.WriteLine(thread.Name + " start");
  107. thread.Start();
  108. Thread.Sleep(2000);
  109. }
  110. }
  111. private static Message ConvertToMsg(TmcMessage tmcMsg)
  112. {
  113. var msg = new Message
  114. {
  115. Id = tmcMsg.Id,
  116. Topic = tmcMsg.Topic,
  117. PubAppKey = tmcMsg.PubAppKey,
  118. PubTime = Convert.ToDateTime(tmcMsg.PubTime),
  119. UserId = tmcMsg.UserId,
  120. UserNick = tmcMsg.UserNick,
  121. Content = tmcMsg.Content
  122. };
  123. return msg;
  124. }
  125. private void HandleMessage(TmcMessage msg)
  126. {
  127. if (OnMessage == null)
  128. {
  129. return;
  130. }
  131. ThreadPool.QueueUserWorkItem(o =>
  132. {
  133. if (!_running)
  134. {
  135. Logger.Info($"message dropped as client closed: {msg}");
  136. return;
  137. }
  138. var args = new MessageArgs(ConvertToMsg(msg), m => this.Confirm(m.Id));
  139. var sw = new Stopwatch();
  140. try
  141. {
  142. sw.Start();
  143. OnMessage(this, args);
  144. sw.Stop();
  145. }
  146. catch (Exception e)
  147. {
  148. args.Fail(e.Message);
  149. }
  150. if (args._isFail)
  151. {
  152. Logger.Info("process message error: {0}", args._reason);
  153. // 不执行确认
  154. return;
  155. }
  156. // prevent confirm attach
  157. if (sw.ElapsedMilliseconds <= 1)
  158. {
  159. Thread.Sleep(10);
  160. }
  161. if (args._isConfirmed)
  162. {
  163. return;
  164. }
  165. try
  166. {
  167. Confirm(msg.Id);
  168. if (EnableTraceLog)
  169. {
  170. Logger.Info("confirm message topic: {0}, id: {1}", msg.Topic, msg.Id);
  171. }
  172. }
  173. catch (Exception e)
  174. {
  175. Logger.Warn($"confirm message {msg} error {e.StackTrace}");
  176. }
  177. });
  178. }
  179. private void Confirm(long id)
  180. {
  181. var cReq = new TmcMessagesConfirmRequest
  182. {
  183. GroupName = _groupName,
  184. SMessageIds = id.ToString()
  185. };
  186. _topClient.Execute(cReq);
  187. }
  188. public void Close()
  189. {
  190. _running = false;
  191. Console.WriteLine("TmcApiClient Stop");
  192. }
  193. }
  194. }