给出以下情况:
1. 通过Post请求将新工作发送到API。该API返回JobID和HTTP响应代码202。 2. 然后使用该JobID请求状态终端点。如果响应正文中设置了“已完成”属性,则可以继续执行步骤3。 3. 使用JobID查询结果终端点并可进行处理。
我的问题是如何优雅、干净地解决这个问题。是否已经有现成的库实现了这个功能?我在RestSharp或其他HttpClient中找不到这样的功能。当前的解决方案如下:
1. 通过Post请求将新工作发送到API。该API返回JobID和HTTP响应代码202。 2. 然后使用该JobID请求状态终端点。如果响应正文中设置了“已完成”属性,则可以继续执行步骤3。 3. 使用JobID查询结果终端点并可进行处理。
我的问题是如何优雅、干净地解决这个问题。是否已经有现成的库实现了这个功能?我在RestSharp或其他HttpClient中找不到这样的功能。当前的解决方案如下:
async Task<string> PostNewJob()
{
var restClient = new RestClient("https://baseUrl/");
var restRequest = new RestRequest("jobs");
//add headers
var response = await restClient.ExecutePostTaskAsync(restRequest);
string jobId = JsonConvert.DeserializeObject<string>(response.Content);
return jobId;
}
async Task WaitTillJobIsReady(string jobId)
{
string jobStatus = string.Empty;
var request= new RestRequest(jobId) { Method = Method.GET };
do
{
if (!String.IsNullOrEmpty(jobStatus))
Thread.Sleep(5000); //wait for next status update
var response = await restClient.ExecuteGetTaskAsync(request, CancellationToken.None);
jobStatus = JsonConvert.DeserializeObject<string>(response.Content);
} while (jobStatus != "finished");
}
async Task<List<dynamic>> GetJobResponse(string jobID)
{
var restClient = new RestClient(@"Url/bulk/" + jobID);
var restRequest = new RestRequest(){Method = Method.GET};
var response = await restClient.ExecuteGetTaskAsync(restRequest, CancellationToken.None);
dynamic downloadResponse = JsonConvert.DeserializeObject(response.Content);
var responseResult = new List<dynamic>() { downloadResponse?.ToList() };
return responseResult;
}
async main()
{
var jobId = await PostNewJob();
WaitTillJobIsReady(jobID).Wait();
var responseResult = await GetJobResponse(jobID);
//handle result
}
正如@Paulo Morgado所说,我不应该在生产代码中使用Thread.Sleep / Task Delay。但是在我看来,我必须在方法WaitTillJobIsReady()中使用它吗?否则,在循环中使用Get请求会使API过载?
在这种情况下,最佳实践是什么?
Thread.Sleep(...)
,而应该使用await Task.Delay(...)
。在生产代码中,两者都不应该使用。 - Paulo MorgadoHttpClient
替代 RestSharp。 - Paulo Morgado