I have below C# code that runs periodically, e.g., every 1 hour. Every time it runs, it tries to make some remote calls in parallel. When any of these remote calls throws an exception, I create only one ticket, or update the previous ticket. And in the finally block, resolve the existing previous ticket if there is no exception this time. Essentially I want to make sure that no matter how many remote calls fail, I only have one ticket to investigate. And when next time all calls succeed, the ticket gets resolved automatically.
However, when the remote calls all succeed in the try block, the call in finally block tries to resolve the ticket, but ran into HTTP 412 Precondition Failed, meaning that the ticket I got in try block was somehow updated before the finally block. If it's updated in the same thread, I wouldn't try to resolve it.
I learnt from this post that Task.WhenAll
will wait for all tasks to complete even in the presence of failures (faulted or canceled tasks). In case where multiple tasks throw exceptions, would the catch block run once or more? How about the finally block?
Ticket ticket = null;
try
{
// Query to get the existing ticket if there is any.
ticket = await QueryExistingTicketAsync();
// Make a lot of remote calls in parallel
var myTasks = new List<Task>();
myTasks.Add(RemoteCallAsync("call1"));
myTasks.Add(RemoteCallAsync("call2"));
myTasks.Add(RemoteCallAsync("call3"));
// ... add more Tasks for RemoteCallAsync()
await Task.WhenAll(myTasks);
}
catch (Exception ex)
{
if (ticket != null)
{
ticket.ReChecked = true;
ticket.LastCheckTime = DateTimeOffset.Now;
// If the previous ticket exists, meaning the last run failed as well,
// update the timestamp on that ticket.
ticket = await UpdateExistingTicketAsync(ticket);
}
else
{
// If the previous ticket does not exist yet,
// create one ticket for investigation, this ticket.ReChecked will be true
ticket = await CreateNewTicketAsync();
}
}
finally
{
// Resolve the previous ticket if it was not created/updated in catch block
if (ticket != null && !ticket.ReChecked)
{
ticket.Status = "Resolved";
await UpdateExistingTicketAsync(ticket);
}
}