using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace Top.Api { /// /// 调用出错自动重试客户端。 /// public class AutoRetryTopClient : DefaultTopClient { private static readonly TopException RETRY_FAIL = new TopException("sdk.retry-call-fail", "API调用重试失败"); /// /// 单次请求的最大重试次数,默认值为3次。 /// private int maxRetryCount = 3; /// /// 重试之前休眠时间,默认值为100毫秒。 /// private int retryWaitTime = 100; /// /// 超过最大重试次数时是否抛出异常。 /// private bool throwIfOverMaxRetry = false; /// /// 自定义重试错误码列表。 /// private IDictionary retryErrorCodes; public AutoRetryTopClient(string serverUrl, string appKey, string appSecret) : base(serverUrl, appKey, appSecret) { } public AutoRetryTopClient(string serverUrl, string appKey, string appSecret, string format) : base(serverUrl, appKey, appSecret, format) { } public override T Execute(ITopRequest request) { return Execute(request, null); } public override T Execute(ITopRequest request, string session) { return Execute(request, session, DateTime.Now); } public override T Execute(ITopRequest request, string session, DateTime timestamp) { T rsp = null; TopException exp = null; for (int i = 0; i < maxRetryCount; i++) { if (i > 0) { if ((rsp != null && ((rsp.SubErrCode != null && rsp.SubErrCode.StartsWith("isp.")) || (retryErrorCodes != null && retryErrorCodes.ContainsKey(rsp.SubErrCode)))) || exp != null) { Thread.Sleep(retryWaitTime); topLogger.Warn(BuildRetryLog(request.GetApiName(), request.GetParameters(), i)); } else { break; } } try { rsp = base.Execute(request, session); if (rsp.IsError) { if (i == maxRetryCount && throwIfOverMaxRetry) { throw RETRY_FAIL; } } else { return rsp; } } catch (TopException e) { if (exp == null) { exp = e; } } } if (exp != null) { throw exp; } else { return rsp; } } public void SetMaxRetryCount(int maxRetryCount) { this.maxRetryCount = maxRetryCount; } public void SetRetryWaitTime(int retryWaitTime) { this.retryWaitTime = retryWaitTime; } public void SetThrowIfOverMaxRetry(bool throwIfOverMaxRetry) { this.throwIfOverMaxRetry = throwIfOverMaxRetry; } public void AddRetryErrorCode(string errorCode) { if (this.retryErrorCodes == null) { this.retryErrorCodes = new Dictionary(); } this.retryErrorCodes.Add(errorCode, false); } private string BuildRetryLog(string apiName, IDictionary parameters, int retryCount) { StringBuilder sb = new StringBuilder(); sb.Append(apiName).Append(" retry call ").Append(retryCount); if (parameters.ContainsKey("fields")) { parameters.Remove("fields"); } sb.Append(" times, parameters=").Append(parameters); return sb.ToString(); } } }