chenhaozhe
2 天以前 d7f3369550e06d123fc959f8da3549535c2a5afe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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();
        }
    }
}