Sequential Processing in a Logic App

In a Logic App, I wanted to process a number of descriptions sequentially, but the descriptions were processed out of order. How come?

By default, “For each” iterations run at the same time, or in parallel. To run sequentially, you must enable Concurrency Control in the settings of the ForEach loop and then set the limit to 1.

It’s as easy as that, but quite hard to pinpoint if you are not aware of this default behavior. Use it to your advantage!

ForEach Queue Message

I had a logic app that started with a queue trigger followed by a ForEach statement. The Logic App run failed on the ForEach step with the following error message:

ExpressionEvaluationFailed. The execution of template action ‘For_each’ failed: the result of the evaluation of ‘foreach’ expression ‘@triggerBody()?[‘QueueMessagesList’]?[‘QueueMessage’]’ is of type ‘Null’. The result must be a valid array.

Stop searching for a solution and go to the settings of the queue trigger by clicking the dots in the Logic App Designer. You will notice that the option Split On is enabled by default. That’s the problem. You can’t use a ForEach on the queue messagelist when the contents of the queue are already split. Disable Split On. Concurrency Control will automatically be switched on. Use the slider to set Degree of Parallelism to 1. You don’t have to set this option to 1, it’s just the safest option (nothing happening in parallel).

Note. When you deploy a logic app, the trigger is no longer run automatically. That’s a recent Azure change you should be aware of. Actually very nice, because there might be cases you don’t want to have the trigger going off automatically to prevent errors from happening.

LogicApp Debatching using SplitOn

Debatching is a common need in enterprise integration. I found a very informative link on using SplitOn with either json or xml as the input message.

Link: Blog Toon Vanhoutte

From an exception handling perspective this approach is neat, because you get a separate logic app for each array item. All these logic apps can run and be resubmitted independently. Compare this with a foreach construct where there’s only one parent logic app that fails when one of the child logic apps fails. There’s one important gotcha. If you do nothing and send an invalid message the SplitOn action may fail. That’s why it’s good practice to always validate the message before SplitOn. For json messages you can use the Parse Json action.

The logic apps are separate when using the SplitOn command, but you can relate them using the CorrelationID. For querying logic apps yoyu can use Logic Apps Management REST API.

ForEach in LogicApp

I have struggled a while to get ForEach looping working in my logic app. In this scenario I call an Azure Function FilterEvents (post), to filter the results from an Http Call. The output of this function is an array. So I added a ForEach loop to go through the array. Within the ForEach section, you have an element named actions. Here you will have to add the actions you want to include in your loop. Makes sense, but I didn’t know I could nest actions that way. Next note the element foreach with value @body(‘FilterEvents’). This means you are going through the output of the FilterEvents action one by one. Finally the most important part: How do you refer to the items in the array? As you can see, that’s via the Item element: @{item().IntegrationId}. Note that I don’t want to return json, but a string. That’s why I use the expression notation @{ …}, so with the curly braces. Within the loop I call a child workflow. Like I said, you can add multiple actions within a loop, but I wanted a bit more modularization.

“FilterEvents”: {
“type”: “Function”,
“inputs”: {
“body”: “@body(‘HTTP’)”,
“function”: {
“id”: “/subscriptions/1ea9735d-00df-4375-86d5-d0d35362dd7f/resourceGroups/ahak-appfunctions/providers/Microsoft.Web/sites/ahak-functions/functions/FilterEvents”
}
},
“runAfter”: {
“HTTP”: [
“Succeeded”
]
}
},
“ForEachEvent”: {
“type”: “Foreach”,
“foreach”: “@body(‘FilterEvents’)”,
“actions”: {
“ProcessAGADocuments”: {
“type”: “Workflow”,
“inputs”: {
“host”: {
“triggerName”: “manual”,
“workflow”: {
“id”: “/subscriptions/1ea9735d-00df-4375-86d5-d0d35362dd7f/resourceGroups/ahak-appservices/providers/Microsoft.Logic/workflows/ProcessAGADocuments”
}
},
“body”: {
“IntegrationId”: “@{item().IntegrationId}”
}
},
“runAfter”: {}
}
},
“runAfter”: {
“FilterEvents”: [
“Succeeded”
]
}
}
}