I am working on a worker service. In this worker service, I am calling a web API of mine that calls an external API. My web API is an asp.net core web API saves requests and responses into database. This external web API returns online game codes.(I am sending how many game codes and for which game.) In a single request there are maximum of 10 codes. The user enters the total amount of online codes and the game number from a blazor server web application. Behind the scenes, this total amount of codes are divided into 20 codes each and are saved into database. The reason why it is saved as 20 is because I am sending 2 parallel tasks to the web API in Parallel.ForEachAsync
in my worker service. This worker service checks the database if there is a record which status = 0
, it gets this record and starts the process.
For example;
Below are 20 coupon requests waiting to be processed in the screenshot. When the worker service receives this record (status = 0) from the database and sends it to my ASP.NET Core web API, then the external API is called 10 by 10 from my API. (Because I want the maximum number of game codes to receive in 1 request.) Therefore, in this scenario, 2 requests will be sent parallel, and 2 responses will be returned. The reason why I make 2 tasks with Parallel.ForEachAsync in the worker is to speed up the process a little more because sometimes a total of 20.000 game codes are requested.
Here is a portion of worker service where I am calling my API. If the responses are a success, I am updating the status = 1
to the database table above saying that this job is completed. In this particular scenario, if both threads/tasks return success there is no problem. The row in the database will be updated, status = 1. If both threads are failed again no problem. (still status = 0, worker service will try it again after a random time interval) But if one thread/task is a success and the other one is failed, the update data method still updates the record which is wrong logic. 1 successful response was received from the external API and saved in the database, but the update method in the worker service updated the record as status=1
. Only 10 game codes have been received. Since there is no logic for checking each task's status, this is causing a problem because only one task ran successfully so only 10 codes were returned. But the database has been updated for 20 codes due to the fact that the task states are not checked separately.
var num = 20;
var firstNum = 10;
var secondNum = 10;
if (num < 20)
{
firstNum = (num + 1) / 2;
secondNum = num - firstNum;
}
var quantities = new List<int> { firstNum, secondNum };
var cts = new CancellationTokenSource();
ParallelOptions parallelOptions = new()
{
MaxDegreeOfParallelism = 2,
CancellationToken = cts.Token
};
try
{
await Parallel.ForEachAsync(quantities, parallelOptions,
async (quantity, ct) =>
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("productCode", productCode),
new KeyValuePair<string, string>("quantity", quantity.ToString()),
new KeyValuePair<string, string>("clientTrxRef", bulkId.ToString())
});
try
{
using var response =
await httpClient.PostAsync(_configuration["Razer:Production"],
content, ct);
if ((int)response.StatusCode == 200)
{
var coupon = await response.Content.ReadFromJsonAsync<Root>(cancellationToken: ct);
await UpdateData(id);
}
else
{
//logging
}
}
catch (HttpRequestException ex)
{
//logging
}
});
}
catch (OperationCanceledException ex)
{
//logging
}
Is there a way to get the statuses of each task so that I can build logic for my problem?