C# 用于.Net的Google API客户端:在请求失败时实现重试
当与google的API交互时,作为批处理请求一部分的请求失败时,如何实现重试。在他们的报告中,他们建议增加“指数退避”算法。我在他们的文档中使用了以下代码片段:C# 用于.Net的Google API客户端:在请求失败时实现重试,c#,google-api,google-calendar-api,google-api-dotnet-client,C#,Google Api,Google Calendar Api,Google Api Dotnet Client,当与google的API交互时,作为批处理请求一部分的请求失败时,如何实现重试。在他们的报告中,他们建议增加“指数退避”算法。我在他们的文档中使用了以下代码片段: UserCredential credential; using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read)) { credential = await GoogleWebAuthorizationBro
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { CalendarService.Scope.Calendar },
"user", CancellationToken.None, new FileDataStore("Calendar.Sample.Store"));
}
// Create the service.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Google Calendar API Sample",
});
// Create a batch request.
var request = new BatchRequest(service);
request.Queue<CalendarList>(service.CalendarList.List(),
(content, error, i, message) =>
{
// Put your callback code here.
});
request.Queue<Event>(service.Events.Insert(
new Event
{
Summary = "Learn how to execute a batch request",
Start = new EventDateTime() { DateTime = new DateTime(2014, 1, 1, 10, 0, 0) },
End = new EventDateTime() { DateTime = new DateTime(2014, 1, 1, 12, 0, 0) }
}, "YOUR_CALENDAR_ID_HERE"),
(content, error, i, message) =>
{
// Put your callback code here.
});
// You can add more Queue calls here.
// Execute the batch request, which includes the 2 requests above.
await request.ExecuteAsync();
UserCredential凭证;
使用(var stream=newfilestream(“client_secrets.json”、FileMode.Open、FileAccess.Read))
{
凭证=等待GoogleWebAuthorizationBroker.AuthorizationAsync(
GoogleClientSecrets.Load(stream.Secrets),
新[]{CalendarService.Scope.Calendar},
“用户”,CancellationToken.None,新文件数据存储(“Calendar.Sample.Store”);
}
//创建服务。
var service=new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer=凭证,
ApplicationName=“谷歌日历API示例”,
});
//创建批处理请求。
var请求=新批处理请求(服务);
request.Queue(service.CalendarList.List(),
(内容、错误、i、消息)=>
{
//把你的回拨码放在这里。
});
request.Queue(service.Events.Insert(
新事件
{
Summary=“了解如何执行批处理请求”,
Start=neweventdatetime(){DateTime=newdatetime(2014,1,1,10,0,0)},
End=neweventdatetime(){DateTime=newdatetime(2014,1,1,12,0,0)}
},“您的日历ID在此”),
(内容、错误、i、消息)=>
{
//把你的回拨码放在这里。
});
//您可以在此处添加更多队列呼叫。
//执行批处理请求,其中包括上述2个请求。
等待请求。ExecuteAsync();
这里有一个简单的助手类,可以很容易地为Google在API错误页面上提到的许多情况实现指数退避:
如何使用:
- 编辑下面的类,以便在上设置时包含客户端密码和应用程序名称
- 在应用程序启动时(或当您要求用户授权时),调用
GCalAPIHelper.Instance.Auth()代码>
- 您可以在任何地方调用Google日历API(例如Get、Insert、Delete等),而是通过执行以下操作来使用此类:
GCalAPIHelper.Instance.CreateEvent(event、calendarId)代码>(您可能需要根据需要将此类扩展到其他API端点)
使用谷歌;
使用Google.api.Auth.OAuth2;
使用Google.api.Calendar.v3;
使用Google.api.Calendar.v3.Data;
使用Google.api.Services;
使用Google.api.Util.Store;
使用制度;
使用System.IO;
使用System.Linq;
Net系统;
使用系统文本;
使用系统线程;
使用静态Google.api.Calendar.v3.CalendarListResource.ListRequest;
/*======================================================================================
*此文件用于实现具有指数回退的Google Calendar.NET API端点。
*
*如何使用:
*-安装Google Calendar.NETAPI(nuget.org/packages/Google.API.Calendar.v3)
*-编辑下面的类,以在需要时包含客户端密码和应用程序名称
*建立在https://console.developers.google.com
*-在应用程序启动时(或当您要求用户授权时),请拨打
*GCalAPIHelper.Instance.Auth();
*-您可以在任何地方调用Google日历API(例如获取、插入、删除等),
*而是通过执行以下操作来使用该类:
*GCalAPIHelper.Instance.CreateEvent(事件,日历ID);(您可能需要扩展
*根据您的需要将该类添加到其他API端点)
*======================================================================================
*/
名称空间APIHelper
{
公共类GCalAPIHelper
{
#区域单态
私有静态GCalAPIHelper实例;
公共静态GCalAPIHelper实例
{
收到
{
if(实例==null)
实例=新的GCalAPIHelper();
返回实例;
}
}
#端区单态
#区域私有财产
专用日历服务服务{get;set;}
私有字符串[]范围={CalendarService.Scope.Calendar};
private const string CLIENTSECRETSTRING=“YOUR_SECRET”//在此处粘贴您的JSON客户端密码。别忘了转义特殊字符!
private const string APPNAME=“您的\u应用程序\u名称”;//在此处粘贴您的应用程序名称
#endregion私有财产
#区域构造函数和初始化
公共GCalAPIHelper()
{
}
公共void身份验证(字符串credentialsPath)
{
if(服务!=null)
回来
用户凭证;
byte[]byteArray=Encoding.ASCII.GetBytes(CLIENTSECRETSTRING);
使用(var流=新内存流(byteArray))
{
凭证=GoogleWebAuthorizationBroker.AuthorizationAsync(
GoogleClientSecrets.Load(stream.Secrets),
范围,
Environment.UserName,
取消令牌。无,
新文件数据存储(credentialsPath,true))。结果;
}
服务=新日历服务(新BaseClientService.Initializer()
{
HttpClientInitializer=凭证,
ApplicationName=APPNAME
});
}
#endregion构造函数和初始化
#区域私有方法
private Trense DoAction with ExponentialBackoff(CalendarBaseServiceRequest)
{
返回DOActionWithExponentalBackoff(请求,新的HttpStatusCode[0]);
}
private Trense DoActionWithExponentialBackoff(CalendarBaseServiceRequest请求、HttpStatusCode[]其他BackoffCodes)
{
int延迟=100;
while(delay<1000)//如果延迟超过1秒,请放弃
private async Task<TResponse> DoActionWithExponentialBackoff<TResponse>(DirectoryBaseServiceRequest<TResponse> request)
{
return await DoActionWithExponentialBackoff(request, new HttpStatusCode[0]);
}
private async Task<TResponse> DoActionWithExponentialBackoff<TResponse>(DirectoryBaseServiceRequest<TResponse> request, HttpStatusCode[] otherBackoffCodes)
{
int timeDelay = 100;
int retries = 1;
int backoff = 1;
while (retries <= 5)
{
try
{
return await request.ExecuteAsync();
}
catch (GoogleApiException ex)
{
if (ex.HttpStatusCode == HttpStatusCode.NotFound)
return default;
else if (ex.HttpStatusCode == HttpStatusCode.Forbidden || //Rate limit exceeded
ex.HttpStatusCode == HttpStatusCode.ServiceUnavailable || //Backend error
ex.Message.Contains("That’s an error") || //Handles the Google error pages like https://i.imgur.com/lFDKFro.png
otherBackoffCodes.Contains(ex.HttpStatusCode))
{
//Common.Log($"Request failed. Waiting {delay} ms before trying again");
Thread.Sleep(timeDelay);
timeDelay += 100 * backoff;
backoff = backoff * (retries++ + 1);
}
else
throw ex; // rethrow exception
}
}
throw new Exception("Retry attempts failed");
}