简体   繁体   中英

Executing a loop in a durable functions orchestrator

I want to send several requests to an external endpoint using a loop in a durable functions orchestrator. (I don't want to do it in parallel because of limiting in the external service.)

foreach (input in inputs)
{
    await context.CallActivityAsyncWithRetry("PostRequest", retryOptions, input);
}

From my testing, if the first request fails (after retrying according to my retryOptions) the rest of the foreach fails. Even if I wrap the request in a try/catch which swallows the failure, if the first request fails then the foreach gives up.

foreach (input in inputs)
{
    try
    {
        await context.CallActivityAsyncWithRetry("PostRequest", retryOptions, input);
    }
    catch (Exception e){}
}

Can anyone recommend a way of dealing with this? Create a sub-orchestration for each input? If any of the preceeding requests fails (after retryOptions specified), I still want to try and execute the subsequent requests in the input list.

Loop

foreach (input in inputs)
{
  await PostRequest(dataType input);
}

Then you must have a function to handle two operations, sending a request and handle failure

public async Task PostRequest(dataType input)
{

  try
  {
    await context.CallActivityAsyncWithRetry("PostRequest", retryOptions, input);
  }
   catch (Exception e)
  {
      //handle failure 
      //retry
  }

}

In my view each activity that you call from main trigger function has to handle exception and throw that exception. It is good if you post what is inside postrequest.

  • From your code currently it will execute one by one ( Means it execute and wait for first one to finish).
 var tasks= new List<Task>();
foreach (input in inputs)
{
   var currentTask = context.CallActivityAsyncWithRetry("PostRequest", retryOptions, input);
  currentTask.ContinueWith(ss => Console.WriteLine(ss) , TaskContinuationOptions.OnlyOnFaulted);
  tasks.Add(currentTask);
}

Task.WaitAll(tasks);

You are following a durable functions pattern called function chaining. But I think you could perhaps code your activities to handle exceptions and then report back to the orchestrator with a success (and possibly data) or with a failure (and possibly a reason).

I put a Polly retry in my activity for normal transient HTTP errors. I reserve the activity level retry for bigger issues. For example the service I am trying to query being too busy to respond in a timely manner. After 3 Polly retries I give up & fail the activity with a reason. I use the activity retry to wait a much longer period before trying the activity again.

My orchestration reports on success/failure of on-going activities including failure reasons.

Finally the after all retries are done, the orchestrator will give the full picture.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM