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();
|
}
|
}
|
}
|