using System; 
 | 
using System.Collections.Generic; 
 | 
using System.Text; 
 | 
using System.Threading; 
 | 
  
 | 
namespace Top.Api 
 | 
{ 
 | 
    /// <summary> 
 | 
    /// 调用出错自动重试客户端。 
 | 
    /// </summary> 
 | 
    public class AutoRetryTopClient : DefaultTopClient 
 | 
    { 
 | 
        private static readonly TopException RETRY_FAIL = new TopException("sdk.retry-call-fail", "API调用重试失败"); 
 | 
  
 | 
        /// <summary> 
 | 
        /// 单次请求的最大重试次数,默认值为3次。 
 | 
        /// </summary> 
 | 
        private int maxRetryCount = 3; 
 | 
        /// <summary> 
 | 
        /// 重试之前休眠时间,默认值为100毫秒。 
 | 
        /// </summary> 
 | 
        private int retryWaitTime = 100; 
 | 
        /// <summary> 
 | 
        /// 超过最大重试次数时是否抛出异常。 
 | 
        /// </summary> 
 | 
        private bool throwIfOverMaxRetry = false; 
 | 
        /// <summary> 
 | 
        /// 自定义重试错误码列表。 
 | 
        /// </summary> 
 | 
        private IDictionary<string, bool> 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<T>(ITopRequest<T> request) 
 | 
        { 
 | 
            return Execute<T>(request, null); 
 | 
        } 
 | 
  
 | 
        public override T Execute<T>(ITopRequest<T> request, string session) 
 | 
        { 
 | 
            return Execute<T>(request, session, DateTime.Now); 
 | 
        } 
 | 
  
 | 
        public override T Execute<T>(ITopRequest<T> 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<string, bool>(); 
 | 
            } 
 | 
            this.retryErrorCodes.Add(errorCode, false); 
 | 
        } 
 | 
  
 | 
        private string BuildRetryLog(string apiName, IDictionary<string, string> 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(); 
 | 
        } 
 | 
    } 
 | 
} 
 |