Azure Function Exponential Retry

What’s the default retry interval for a Http action in a logic app? How do I specify an exponential retry interval? I performed a little experiment in Azure to find the answers. 

First I created a Http triggered Azure function. The function gets the name node of the request body using data.name instead of data?name. Using data.name, I simply assume the name node is always present. Bad coding, but fit for my case. Next I created a logic app with a Http action calling the function. To enforce a Http 500 exception, I simply trigger the logic app without passing a message body. The Http 500 in turn, results in a retry which I’m after. Note that the retry interval must be specified in ISO8601 format, which is like: PTxxxH/M/S.

Here are the results:

Default retry:

This policy sends up to four retries at exponentially increasing intervals, which scale by 7.5 seconds but are capped between 5 and 45 seconds.

  • Run 09:04:17
  • Retry 09:04:17
  • Retry 09:04:23
  • Retry 09:04:34
  • Retry 09:05:01

Retry 5 times, interval=5S, min interval=5S, max interval=2M

  • Run 09:11:15
  • Retry 09:11:15
  • Retry 09:11:20
  • Retry 09:11:31
  • Retry 09:11:45
  • Retry 09:12:14

Retry 8 times, interval 10S, min interval 5S, max interval 2M

  • Run 09:16:35
  • Retry 09:16:35
  • Retry 09:16:40
  • Retry 09:16:59
  • Retry 09:17:25
  • Retry 09:18:19
  • Retry 09:20:19
  • Retry 09:22:19
  • Retry 09:24:19

Retry 5 times, interval=1M, min interval=30S, max interval=3M

  • Run 09:27:49
  • Retry 09:27:49
  • Retry 09:28:22
  • Retry 09:29:43
  • Retry 09:32:44
  • Retry 09:35:44

Resume:

  • The first retry occurs immediately (both for exponential retry interval and fixed retry interval).
  • The min interval must be between 00:00:05 and the interval specified.
  • The second retry occurs between min interval and interval. It can be equal to min interval, but that doesn’t have to be the case.
  • The max interval is the max retry interval. The retries don’t have to be capped before the max interval (as the default interval states).

Retry in Logic Apps

//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js

(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: “ca-pub-1655089477432243”,
enable_page_level_ads: true
});

For easy reference this information is taken from the Microsoft Azure site.

HTTP actions and API Connections (like the Azure Storage API, SharePoint API or child workflows) support retry policies.  A retry policy applies to intermittent failures (characterized as HTTP status codes 4xx (408, 429) and 5xx as well as any connectivity exceptions) and is described using the retryPolicy object.

The retry interval is specified in the ISO 8601 format.  Its default value is 20 seconds, which is also the minimum value. The maximum value is 1 hour. The default retry count is 4. 4 is also the maximum retry count. To disable the retry policy, set its type to None.

[box type=”error”] If you don’t add a retry interval, the default retry interval will be applied. The default retry policy is: 4 retries with a 20 second interval [/box]

In the example below, we have defined a retry policy that will retry an action 2 time in case of intermittent failures, for a total of 3 executions, with a 30 second delay between each attempt:

“PostAGAssets”:
“retryPolicy” : {
“type”: “fixed”,
“interval”: “PT30S”,
“count”: 2
}
For an expanation of the ISO8601 interval notation, see the following link.
[box type=”warning”] Retry seems like a good idea, but it may have a counterproductive effect in the Azure Portal. Because of all the retries we see five failing logic app runs, not just one. This situation gets worse if we use nested workflows.[/box]
In the example below we see a child workflow being called with a retry interval None. Next we see a Http action. Note that the retry policy is contained in the inputs section of the action.

Child workflow:
“ProcessAGADocument”:
{
“type”: “Workflow”,
“inputs”: {
“host”: {
“triggerName”: “manual”,
“workflow”: {
“id”: “[concat(‘/subscriptions/1ea9735d-00df-4375-86d5-d0d35362dd7f/resourceGroups/’, variables(‘rg’), ‘/providers
/Microsoft.Logic/workflows/’, parameters(‘logicAppProcessAGADocument’))]”
}
},
“body”: {
“RegionCode”: “@{triggerBody()[‘RegionCode’]}”,
“BestandsNaam”: “@{item().BestandsNaam}”,
“DocumentId”: “@{item().DocumentId}”,
“IntegrationId”: “@{body(‘ConvertIntegrationId’).IntegrationId}”,
“FormCode”: “@{item().FormCode}”,
“DocumentType”: “@{item().DocumentType}”
},
“retryPolicy”: {
“type”: “none”
}
},
“runAfter”: {}
}
},
“runAfter”: {
“FilterAGAAttachments”: [
“Succeeded”
]
}
}

Http Action:
“GetDocument”:
{
“type”: “Http”,
“inputs”: {
“method”: “GET”,
“uri”: “https://@{encodeURIComponent(parameters(‘gmfBaseUrl’))}/api/gmf/@{triggerBody()[‘RegionCode’]}/document
/@{item().DocumentId}”,
“headers”: {
“PlatformUser”: “[parameters(‘gmfUser’)]”
},
“authentication”: {
“type”: “Basic”,
“username”: “[parameters(‘gmfUser’)]”,
“password”: “[parameters(‘gmfPassword’)]”
},
“retryPolicy”: {
“type”: “none”
}
},
“runAfter”: {}
}

Http Action(2):
“PostAGAFoto”:
{
“type”: “Http”,
“inputs”: {
“method”: “post”,
“queries”: {
“regionCode”: “@{triggerBody()[‘RegionCode’]}”,
“formCode”: “@{triggerBody()[‘FormCode’]}”,
“integrationId”: “@{triggerBody()[‘IntegrationId’]}”,
“documentId”: “@{triggerBody()[‘DocumentId’]}”,
“bestandsNaam”: “@{triggerBody()[‘BestandsNaam’]}”
},
“uri”: “https://@{encodeURIComponent(parameters(‘ahakStorageConnectorName’))}.azurewebsites.net/api/Storage/PostAGAFoto”,
“retryPolicy”: {
“type”: “none”
}
},
“runAfter”: {
“DeleteAGAFoto”: [
“Succeeded”
]
},
“metadata”: {
“apiDefinitionUrl”: “https://@{encodeURIComponent(parameters(‘ahakStorageConnectorName’))}.azurewebsites.net/swagger/docs/v1”,
“swaggerSource”: “website”
}
}