AutoRetryTopClient.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Threading;
  5. namespace Top.Api
  6. {
  7. /// <summary>
  8. /// 调用出错自动重试客户端。
  9. /// </summary>
  10. public class AutoRetryTopClient : DefaultTopClient
  11. {
  12. private static readonly TopException RETRY_FAIL = new TopException("sdk.retry-call-fail", "API调用重试失败");
  13. /// <summary>
  14. /// 单次请求的最大重试次数,默认值为3次。
  15. /// </summary>
  16. private int maxRetryCount = 3;
  17. /// <summary>
  18. /// 重试之前休眠时间,默认值为100毫秒。
  19. /// </summary>
  20. private int retryWaitTime = 100;
  21. /// <summary>
  22. /// 超过最大重试次数时是否抛出异常。
  23. /// </summary>
  24. private bool throwIfOverMaxRetry = false;
  25. /// <summary>
  26. /// 自定义重试错误码列表。
  27. /// </summary>
  28. private IDictionary<string, bool> retryErrorCodes;
  29. public AutoRetryTopClient(string serverUrl, string appKey, string appSecret)
  30. : base(serverUrl, appKey, appSecret)
  31. {
  32. }
  33. public AutoRetryTopClient(string serverUrl, string appKey, string appSecret, string format)
  34. : base(serverUrl, appKey, appSecret, format)
  35. {
  36. }
  37. public override T Execute<T>(ITopRequest<T> request)
  38. {
  39. return Execute<T>(request, null);
  40. }
  41. public override T Execute<T>(ITopRequest<T> request, string session)
  42. {
  43. return Execute<T>(request, session, DateTime.Now);
  44. }
  45. public override T Execute<T>(ITopRequest<T> request, string session, DateTime timestamp)
  46. {
  47. T rsp = null;
  48. TopException exp = null;
  49. for (int i = 0; i < maxRetryCount; i++)
  50. {
  51. if (i > 0)
  52. {
  53. if ((rsp != null && ((rsp.SubErrCode != null && rsp.SubErrCode.StartsWith("isp."))
  54. || (retryErrorCodes != null && retryErrorCodes.ContainsKey(rsp.SubErrCode)))) || exp != null)
  55. {
  56. Thread.Sleep(retryWaitTime);
  57. topLogger.Warn(BuildRetryLog(request.GetApiName(), request.GetParameters(), i));
  58. }
  59. else
  60. {
  61. break;
  62. }
  63. }
  64. try
  65. {
  66. rsp = base.Execute(request, session);
  67. if (rsp.IsError)
  68. {
  69. if (i == maxRetryCount && throwIfOverMaxRetry)
  70. {
  71. throw RETRY_FAIL;
  72. }
  73. }
  74. else
  75. {
  76. return rsp;
  77. }
  78. }
  79. catch (TopException e)
  80. {
  81. if (exp == null)
  82. {
  83. exp = e;
  84. }
  85. }
  86. }
  87. if (exp != null)
  88. {
  89. throw exp;
  90. }
  91. else
  92. {
  93. return rsp;
  94. }
  95. }
  96. public void SetMaxRetryCount(int maxRetryCount)
  97. {
  98. this.maxRetryCount = maxRetryCount;
  99. }
  100. public void SetRetryWaitTime(int retryWaitTime)
  101. {
  102. this.retryWaitTime = retryWaitTime;
  103. }
  104. public void SetThrowIfOverMaxRetry(bool throwIfOverMaxRetry)
  105. {
  106. this.throwIfOverMaxRetry = throwIfOverMaxRetry;
  107. }
  108. public void AddRetryErrorCode(string errorCode)
  109. {
  110. if (this.retryErrorCodes == null)
  111. {
  112. this.retryErrorCodes = new Dictionary<string, bool>();
  113. }
  114. this.retryErrorCodes.Add(errorCode, false);
  115. }
  116. private string BuildRetryLog(string apiName, IDictionary<string, string> parameters, int retryCount)
  117. {
  118. StringBuilder sb = new StringBuilder();
  119. sb.Append(apiName).Append(" retry call ").Append(retryCount);
  120. if (parameters.ContainsKey("fields"))
  121. {
  122. parameters.Remove("fields");
  123. }
  124. sb.Append(" times, parameters=").Append(parameters);
  125. return sb.ToString();
  126. }
  127. }
  128. }