Web API轮询 C#

huangapple go评论61阅读模式
英文:

Web api polling C#

问题

我想在 asp.net core 应用程序中使用轮询机制调用第三方 Rest API。

在下面的示例代码中,我想使用 _client.DocumentProcess(model) API,每隔 10 秒调用一次,最多调用五次,直到获得结果为"Success",或者超过轮询调用限制。

请问有什么最佳实践来解决这个问题吗?
谢谢。
英文:

I want to call one 3rd party Rest API from the asp.net core application with the polling mechanism.

Here in the below sample code, I want to call _client.DocumentProcess(model) API with some polling mechanism after every 10 seconds for five times until I get the Result as "Success" or my polling call limit gets exceeded.

    public async Task<Result> TrackDocumentProcess(RequestModel model)
    {
        var response = await _client.DocumentProcess(model);
        if(response.IsSuccess)
        {
             if(response.Value.Status != "Success")
                //Call the _client.DocumentProcess(model) API after 10 seconds.
             else
                return Result.Success();
        }
    }

    public async Task<Result<ResponseModel>> DocumentProcess(RequestModel model)
	{
		
		var authToken = GetToken();
		using var httpClient = new HttpClient();
		using var request = new HttpRequestMessage(new HttpMethod("POST"), $"https://apiurl.com/api/TrackDocumentProcessStatus/{model.DocumentId}");

		request.Headers.TryAddWithoutValidation("Authorization", $"Bearer {authToken.Result.Value.Token}");
		
		var response = await httpClient.SendAsync(request);
		var content = await response.Content.ReadAsStringAsync();
		if (!string.IsNullOrEmpty(content))
		{
			var userRequestResponse = JsonSerializer.Deserialize<ResponseModel>(content);
            return Result.Success(userRequestResponse);
		}
		return Result.Failure<ResponseModel>("Error...");
	}

Can you please suggest any best practices to solve this problem?
Thanks.

答案1

得分: 2

在下面的示例代码中,我想要调用_client.DocumentProcess(model) API,并在每隔10秒后调用某种轮询机制,重复五次,直到我得到"Success"的结果或轮询调用次数达到限制。

根据您的情况,我们可以考虑两种标准的实现。首先,我们可以使用PeriodicTimer,它提供了一个定期的计时器,会按照给定的时间间隔调用。

另一种方法是使用BackgroundService工作进程,它会持续调用API,直到满足某些条件。

使用PeriodicTimer:

public async Task<IActionResult> DocumentProcess()
{
    var status = await TrackDocumentProcessStatus();

    if (status == "Success")
    {
        return Ok(status);
    }
    else
    {
        var timer = new PeriodicTimer(TimeSpan.FromSeconds(10));

        while (await timer.WaitForNextTickAsync())
        {
            status = await TrackDocumentProcessStatus();
            if (status == "Success")
            {
                break;
            }
        }
    }

    return Ok();
}

Explanation:

如您所见,当调用DocumentProcess方法时,它会调用TrackDocumentProcessStatus方法,然后调用API。如果API返回"Pending",则更新状态,并在接下来的10秒内再次调用,直到获得"Success"状态。

每10秒调用一次的方法:

public async Task<string> TrackDocumentProcessStatus()
{
    var requestObject = new StatusRequestModel();
    requestObject.RequestId = 3;

    var data = JsonConvert.SerializeObject(requestObject);
    HttpClient httpClient = new HttpClient();
    var buffer = System.Text.Encoding.UTF8.GetBytes(data);
    var byteContent = new ByteArrayContent(buffer);
    byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    string url = "http://localhost:5094/api/Rest/CheckDocumentStatus";
    var response = await httpClient.PostAsync(url, byteContent);

    if (response.StatusCode != HttpStatusCode.OK)
    {
        return "Pending";
    }
    string responseData = await response.Content.ReadAsStringAsync();
    return responseData;
}

BackgroundService工作进程:

这将是一个独立的后台工作服务,将持续运行并在后台检查状态。您可以按以下方式满足您的需求:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            var status = await TrackDocumentProcessStatus();
            if (status == "Success")
            {
                break;
            }
            Console.WriteLine(status);
            await Task.Delay(10000, stoppingToken); // 10 seconds delay
        }
    }

    public async Task<string> TrackDocumentProcessStatus()
    {
        var requestObject = new StatusRequestModel();
        requestObject.RequestId = 1;

        var data = JsonConvert.SerializeObject(requestObject);
        HttpClient httpClient = new HttpClient();
        var buffer = System.Text.Encoding.UTF8.GetBytes(data);
        var byteContent = new ByteArrayContent(buffer);
        byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        string url = "http://localhost:5094/api/Rest/CheckDocumentStatus";
        var response = await httpClient.PostAsync(url, byteContent);

        if (response.StatusCode != HttpStatusCode.OK)
        {
            return "Pending";
        }
        string responseData = await response.Content.ReadAsStringAsync();
        return responseData;
    }
}

注意:
这两种实现都会在一定时间间隔后调用您的API以检查另一个API的状态。它们之间的区别在于后台工作服务会在后台持续运行,无需其他操作,就像Windows服务一样。如果您想了解更多关于后台工作服务的详细信息,可以查看我们的官方文档

英文:

> Here in the below sample code, I want to call
> _client.DocumentProcess(model) API with some pooling mechanism after every 10 seconds for five times until I get the Result as "Success" or
> my pooling call limit gets exceeded.

Well based on your scenario, we can consider two standard implementaion. First one we can implement using PeriodicTimer which provides a periodic timer that would call as per the given time interval.

Another one, would be using BackgroundService worker process which would continue calling API unless the certain condition are meet.

Using PeriodicTimer:

public async Task&lt;IActionResult&gt; DocumentProcess()
        {

            var status = await TrackDocumentProcessStatus();

            if (status == &quot;Success&quot;)
            {

                return Ok(status);
            }
            else
            {
                var timer = new PeriodicTimer(TimeSpan.FromSeconds(10));

                while (await timer.WaitForNextTickAsync())
                {
                   status = await TrackDocumentProcessStatus();
                    if (status == &quot;Success&quot;)
                    {
                        break;
                       
                    }
                    continue;
                }
            }

            return Ok();
        }

Explanation:

As you can see, when DocumentProcess method would invocke, it will call the TrackDocumentProcessStatus method thus, the API and if API return pending it update the status and will call again within next 10 seconds and process would continue until it gets success status.

Method Would Invoked Every 10 Seconds:

public async Task&lt;string&gt; TrackDocumentProcessStatus()
        {
            var rquestObject = new StatusRequestModel();
            rquestObject.RequestId = 3;

            var data_ = JsonConvert.SerializeObject(rquestObject);
            HttpClient _httpClient = new HttpClient();
            var buffer_ = System.Text.Encoding.UTF8.GetBytes(data_);
            var byteContent_ = new ByteArrayContent(buffer_);
            byteContent_.Headers.ContentType = new MediaTypeHeaderValue(&quot;application/json&quot;);
            string _urls = &quot;http://localhost:5094/api/Rest/CheckDocumentStatus&quot;;
            var responses_ = await _httpClient.PostAsync(_urls, byteContent_);

            if (responses_.StatusCode != HttpStatusCode.OK)
            {
                return &quot;Pending&quot;;

            }
            string response = await responses_.Content.ReadAsStringAsync();
            return response;

        }

Output:

Web API轮询 C#

Note:
If you would like to know more details on it you could check our official document here

BackgroundService worker process:

It would be a individual background worker service which would continue running and check your status behind. You can achieve your requirement as following:

public class Worker : BackgroundService
    {
        private readonly ILogger&lt;Worker&gt; _logger;

        public Worker(ILogger&lt;Worker&gt; logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation(&quot;Worker running at: {time}&quot;, DateTimeOffset.Now);
                var status = await TrackDocumentProcessStatus();
                status = await TrackDocumentProcessStatus();
                if (status == &quot;Success&quot;)
                {
                    break;

                }
                Console.WriteLine(status);
                await Task.Delay(1000, stoppingToken);
            }
        }

        public async Task&lt;string&gt; TrackDocumentProcessStatus()
        {
            var rquestObject = new StatusRequestModel();
            rquestObject.RequestId = 1;

            var data_ = JsonConvert.SerializeObject(rquestObject);
            HttpClient _httpClient = new HttpClient();
            var buffer_ = System.Text.Encoding.UTF8.GetBytes(data_);
            var byteContent_ = new ByteArrayContent(buffer_);
            byteContent_.Headers.ContentType = new MediaTypeHeaderValue(&quot;application/json&quot;);
            string _urls = &quot;http://localhost:5094/api/Rest/CheckDocumentStatus&quot;;
            var responses_ = await _httpClient.PostAsync(_urls, byteContent_);

            if (responses_.StatusCode != HttpStatusCode.OK)
            {
                return &quot;Pending&quot;;

            }
            string response = await responses_.Content.ReadAsStringAsync();
            return response;

        }

Note:
Both implementaion would call your API after a certain interval for checking status from another API. The difference of these implementation is background worker service would continue in background, no other action wwould required just like widows service, If you would like to know more details on background worker service you could check our official document here

huangapple
  • 本文由 发表于 2023年2月7日 01:13:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75364486.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定