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