Retries with Azure Durable Functions
  • 03 Apr 2022
  • 1 Minute to read
  • Contributors
  • Comments
  • Dark
  • PDF

Retries with Azure Durable Functions

  • Comments
  • Dark
  • PDF

#ServerlessTips - Azure Functions
Author: Steef-Jan Wiggers Azure MVP

With Durable functions, you have support for retries – when calling activity or other orchestration function (sub orchestration). You can customize within the CallActivityWithRetryAsync method, and the RetryOptions class the back-off strategy for retries.

There are several options for customizing the automatic retry policy according to the Microsoft docs - they include the following:

  • Max number of attempts: The maximum number of retry attempts.
  • First retry interval: The amount of time to wait before the first retry attempt.
  • Backoff coefficient: The coefficient used to determine the rate of increase of backoff. Defaults to 1.
  • Max retry interval: The maximum amount of time to wait in between retry attempts.
  • Retry timeout: The maximum amount of time to spend doing retries. The default behaviour is to retry indefinitely.
  • Handle: A user-defined callback can be specified which determines whether or not a function call should be retried.

In the following example we'll retry the MonitorActivity up to a maximum of ten attempts with a 30 seconds delay before retrying.

var monitorActivity = await ctx.CallActivityWithRetryAsync<string>("MonitorActivity", 
               new RetryOptions(TimeSpan.FromSeconds(30),10), inputData);

The code above instructs the framework behind the Durable Functions to:

  • Retry up to ten times
  • Wait 30 seconds before retrying again

When the MonitorActivity is called from the orchestrator and throws an exception - it will be the FunctionFailedException. However, you can examine the inner exception containing the actual exception from the activity and based on that exception you perform a retry.

var a1 = await ctx.CallActivityWithRetryAsync<string>("MonitorActivity", 
    new RetryOptions(TimeSpan.FromSeconds(30),10)
        Handle = ex => ex.InnerException.Message == "Monitoring failed."

When leveraging the RetryOptions class you set the options first:

var options = new RetryOptions(
    firstRetryInterval: TimeSpan.FromMinutes(1),                    
    maxNumberOfAttempts: 10);
options.BackoffCoefficient = 2.0;

Next you set provide the options in the CallActivityWithRetrySync method:

await context.CallActivityWithRetryAsync("MonitorActivity", options, itinerary);

The above code instructs the framework behind the Durable Functions to:

  • Retry up to ten times
  • Wait for one minute before the first retry
  • Increase delays before every subsequent retry by the factor of 2 (1 min, 2 min, 4 min, etc.)
The orchestrator does not block while awaiting retries - after a failed call, a message is scheduled for the moment in the future to re-run the orchestrator and retry the request.

Was this article helpful?