Kevin Lam and Derek Li demonstrate the capabilities of Logic Apps and explains the key best practices, including exception handling.
Integrate 2018, June 4-6, etc.venues, London
Kevin: So you guys know who I am now? Yes? Okay. So, we’ll first step through some workflow patterns and then go into some messaging patterns. Some of the capabilities that we have in Logic Apps are a lot more powerful than you may think, right? One of the things that we’ve tried to do in the designer is give you a really simple experience so that you can do rapid development on top of Logic Apps, so you can get your scenarios done really quickly.
So we give that, you know, very intuitive-seeming, you know, very simple type of designer experience so you can go ahead and get your business process done. But under the covers, we’re actually doing a lot of work for you, and as you lift the covers, there are a lot more capabilities that are actually there for you to take advantage of. Especially, as you get into more of your enterprise integration scenarios and you want to have better assurances that your process will work or be able to deal with bad situations. Because bad situations happen all the time.
The first one is a retry policy, so every action has a default retry policy, and it will retry some exponential random amount of time, up to a minute, four times within that minute. So, 10, seconds, 30 seconds, 20 seconds, and it will retry to create some randomness in that, you know, retry.
You can turn it off in scenarios where you don’t want retries to happen and you wanna fail fast and then to handle that area yourself or you can do a custom retry policy. Either a fixed rate or an exponential rate so that you can go ahead. And if you know that you have certain types of failures that may take a certain amount of time, that you know take five minutes, then, you know, retry after five minutes instead of, you know, just a few seconds.
So, you know, in my previous talks, I noted that we have a graph of connectors…of actions. And that graph is defined by that run-after property, right? It says, “This action will run after step B or A.”
So, in that run after, there’s a few things that you can take advantage of, and I’ll show this in the demo, where you can have conditional dependency control to say, “Hey, I want this to run after step A if it fails.”
So by default, we say, “Run after A if it succeeded,” and that’s the magic you see in the background that we take care of for you. But you have the control to go ahead and manipulate those run-afters so that you can get an error handling experience that you could say, “Run after failure or some time out or if that step has been skipped.”
You can also add a limit, a policy to your Logic App, to your action, and that will limit the duration of that action. So if you want it to only run for 30 seconds, you can put a limit on it for 30 seconds, and then check the status to see if it actually hit that limit versus giving you the answer that you wanted. You don’t block that long in a call.
You can terminate your Logic App, so anywhere within your Logic App, you can decide that you wanna terminate. You know, a typical pattern is that you go ahead and catch an exception, then in that exception, you terminate the action so that it doesn’t do the rest of your workflow.
When you terminate, you can terminate with failed or success. For example, if you’ve handled the error, you don’t want your operators to think that something’s failed because it’s actually been handled so you can terminate with success. So you wanna end your process early.
Finally, there are scopes. Scopes is your ability to have a collection of actions that run, and then have a single output status when it’s complete. So meaning that the scope will have the final status based on the leaf nodes of all the actions that happened within that scope.
So, if a very simple scope just has one or two actions in it, there’s only one leaf node. But you can have sets of parallels in that, as well, and we have to do, essentially, a join across all those leaf nodes to determine what the status of that scope is, and it’ll be essentially an end of all those statuses.
So you can use all these things together to have, you know, for you guys who are more dev-focused, a try-catch-finally pattern, right? That try-catch-finally pattern can be accomplished with Logic Apps, with a set of scopes, and then a set of different run-after policies.
So you would put the actions that you want to execute in that try scope, right? There’s a, your scope, you just, I just happen to call it “try.” And then you have another scope that says, “If the scope has failed, run the actions within this catch scope.”
And then you have a scope after that says, “No matter what’s happened in any scenario, I’ll always want you to execute the actions in this scope,” and that gives you that “finally” step to make sure that it always runs no matter what’s happened before it. All right, so that gives you that try-catch-finally pattern that you can actually build out in Logic Apps.
So that allows you to do, you know, compensation logic or send out detailed error messages to logs or to operators to go handle, you know, a particular scenario or fix a message in, and resend it or whatever that right model is for doing that. But we have that pattern, it’s not very obvious. When you look at a design, it’s like, “Oh, it’s so simple. How do I do, you know, these advanced things?” And we have that capability built in for you.
So concurrency. So, you know, I mentioned in my last talk how Logic Apps is a highly parallelized set of actions that execute in the back end. And so, realizing that, there’s a couple things you should understand. Instances are created concurrently. For example, if I have my Logic App with a request endpoint, and I that request endpoint, and it’s an async call, and I call, call, call. If it’s, you know, that Logic App takes a minute, I don’t have to wait for that Logic App to finish, it will actually create three instances of that Logic App, right? So, instances run concurrently or if I pass it a collection, and I do a split on, then that thing will actually create a number of instances in the background.
Sometimes you don’t want that to happen, either because you have, you don’t want to overwhelm a downstream system, right? Because our Logic App can run highly parallelized, but your downstream system may be a legacy system that can’t handle the type of load, so then you can control that. And in particular, if you have scenarios where you want to do in-order processing of workloads, then you can use a singleton trigger execution.
So you can set that level of parallelism to one or if you just want to control the amount of parallel instances that are running, you can control that in the trigger, as well, with the degrees or parallel value that you have up there, and I’ll show you that in a demo.
So then you also have parallel actions. So in the Logic App, you can actually have two actions or three or four or five run in the parallel in your definition, you can set that up, as well, and then it gets joined with the magic run-after says, “It will run after A, B, and C.” That’s, actually, acts as a join in your Logic App.
For each loops are natively concurrent. So we will take a collection that you pass to the for each loop, and we will run, by default, 20 instances at the same time. So keep that in mind that it actually, and we’ll have some scenarios of why you need to keep that in mind later with Derek’s part of the talk.
So there are scenarios where we want to make that sequential if you need to deal with those items in order. For example, you want to want to have a sequential for each or you want to, for the same reason, not overwhelm a downstream system that’s being hit by that collection, you can control the degrees of parallelism that’s there for you. Or if we want to extend it, as well. Run it faster.
Do-until loops run sequentially, right? By the nature of its intents, which is, “Do something until some state is true. If you do something in parallel, you don’t know what state you’re in.” So it’s a sequential loop that will occur and iterate each time, you know, across the collection of actions you have in that do-until.
So one of the capabilities that Logic Apps has, and is sometimes in a underutilized or unrealized value, is that it has the ability to do scheduled executions. So these kinds of background jobs that you that you’d like to run that do cleanups or, you know, you want to, you know, execute something that’s on a schedule, you know, we have that in the scheduled execution.
So you can have a simple recurrence, every few minutes, every few seconds, every five days. You can have a recurrence with a deterministic time. So I don’t want this job to run until 10 a.m. tomorrow, right? You can have it run exactly at 10 a.m. tomorrow. Or you can have it run at every hour, at midnight, you want to be [inaudible 00:09:47] clock time, you know, with that.
We can do complex schedules, the first and last Sunday of every month at 5 p.m., you can do that, as well, as well as run once jobs. So, in other words, I have a scheduled job that I want to run once. There are a lot of scenarios where ISVs can include this as the implementation detail for jobs that need to run, right?
If I want to, you know, have my device, you know, wake me up and my alarm can actually be a Logic App that’s running in the background. So instead of you having to build that infrastructure to understand, “Hey, I got a thousand devices and, you know, all these schedules that need to run because my customers have set scheduled items: start my car, set an alarm,” you know, all that, you can actually use a Logic App which will then create and manage that schedule for you and then call you back or call whatever API that you want to execute that.
So this is a good scenario for run once jobs. With run once jobs, this is a pattern that you can use so you can have a request trigger that will act as your API to create a time-based job. We will have a delay until in that Logic App and then based on the input that you have for when you want that to fire, then we will sit there and wait for you. And you don’t have to worry about, it’s like, “Oh, if you were to do that on your own, you’d have all this infrastructure that’s sitting there with open sockets and threads.” You know, don’t do that, right? Use Logic Apps.
Then you can have millions of these running, right? These are not definitions, these are not resources, right? These are instances of a Logic App, so you can have lots and lots of these things running in the background, and you get a run ID or you can do an X MS client tracking ID, which is your own tracking ID to map to that item, and then you can call it back and delete it if you need to or see what the status of it is.
Okay, messaging patterns, right? How many guys think of yourselves as Enterprise Integrators? Of course, that’s why you’re here, right? Yeah. So, you know, how many of you read Fowler’s “Enterprise Architecture” book? And the rest of you are just so ashamed that you didn’t read it? Okay. So, you know, there’s a lot of those patterns that are in that book that, even though that’s, you know, that book was written quite some time ago, those patterns are still valid and used a lot today.
So, you know, as you think about the messaging protocols in these patterns, you know, you’ll see these come to light, you know, and the power that you have, and the capabilities you have in Logic Apps to realize those patterns.
So, first I wanna to go through some messaging protocols that we have built-in. Of course, you can do REST and SOAP, you’ve been seeing that throughout the conference, and we can do that with an HTTP action calling out to some REST or SOAP endpoint. You can have it in connectors or you can have it in your custom connectors that are calling out to these REST or SOAP endpoints.
Of course, you can have your own trigger in your Logic App that acts as a receiver for a request, an HTTP request. We have workflow invocation so you can componentize your Logic Apps then call that workflow and we’ll handle the protocol under the covers for calling that workflow. We also have a batch action so that you can send messages to a batch and then have another Logic App with a receive batch which can then handle the batches that are received, and I’ll talk about that in a minute, too.
Queuing. So we have storage queues, M queues, service bus queues, right? So great for asynchronous one-way messaging, pub/sub with service bus topics, and M queue again, so that you can go ahead and do pub/sub across those entities, right?
So now you’re starting to see the patterns, right? How many people use BizTalk? Yes? That’s why you’re at the BizTalk conference. Now, if you’re familiar with the message box, so a typical pattern is to use service bus with topics that would represent, you know, something similar to what you have with the message box today, so that you can create subscriptions to services. And then, you know, instead of pipelines, you’d have Logic Apps that would act as your pipeline, and then they can all communicate across topics creating a loosely coupled set of processes based on subscriptions. Great way to implement that.
Event streams, event hubs, and IOT hubs. I started IOT hubs, that’s one of the connectors that are coming really soon so then you can ingest these types of events. And then finally, eventing for Event Grid so that you can get push notifications of interesting events that are happening either within Azure or your custom topics.
There are a couple different types of messaging communication patterns, right? These, you know, the blue items should be very familiar to you for you guys that are doing enterprise messaging. Direct synchronous messaging, so you can do a request/reply, so that’s blocking. For example, I can do an HTTP action that will actually wait for that synchronous call to come back. Or you can do a call workflow, and you can design your workflow, either sync or async, in this case, so that it’ll wait for that workflow to come back.
Direct asynchronous. You can do a fire-and-forget, so then you call some HTTP endpoint or you can be you can design your Logic App to behave in this way so that it fires and then says, “Okay, I’ll do the work, I promise. Go away.” And you’re happy, so 201. You can do call workflow async, so you return, the async pattern’s 202, where you return the retry after header and the location header, so then it indicates for the caller, “Hey, call this endpoint back in this amount of time and then we’ll tell you when that job’s complete.”
It works both, if you have a service that implements that async pattern and you use our HTTP action, we will actually do that follow for you, so you don’t have to explicitly do that in your Logic App, the HTTP action in the background will follow that 202 pattern.
Fire and wait and poll. So this is when you have like a do-until loop and that you have a status that comes back and it’s a 400, but you’re looking for some content in that status to say that it’s actually done. Sometimes you have scenarios where it’s a 400, but some value happens, means, you know, a lot of people do in their own weird scenarios for their APIs and status codes, so if it’s not a typical pattern, you can still implement it in Logic Apps with a do-until, and HTTP action, and then have a criteria based on that, on the values that are returned.
And then finally, webhook, so then you can register a webhook and we’ll wait until they call us back, right in the middle of the workflow, and that’s what’s done in, for example, the send approval mail. We actually open a webhook and they call us back when it’s done.
Okay, so now getting on the async messaging side, you have message correlation. If you want to send a message and then wait for an asynchronous response to come back, there’s a couple ways to do that. We have correlated messages so that, you know, on the reply message, you get… Sorry. On the request message, you’ll get a reply queue that you want to be able to listen to, that’s response queues or you can use session queues that you’re listening to for that correlation for the set of facts that happen to be correlated, right? In session queues.
For order delivery, we have the singleton pattern, so that as you’re reading messages off a queue, remember I said that we were highly parallelized, but you can actually change that so that it’s running in order and only processing one message at a time.
And finally partitions. So you can have partitioned messaging. Partition messaging will allow you to have, you know, all messages for, you know, if a patient’s going into a hospital, I want all of Bob’s messages as he goes into the hospital to go into one session or be correlated in some way, then you can do that, as well, with partitioning either through batch session queues and topics or sequential convoys. For all you BizTalk guys out there, we do sequential convoys.
Okay, so these one-way messages, we have the ability to do queues, competing consumer, pub/sub, and batch. I think I did this, but it got repeated. So, yes, that slide didn’t get pulled down.
Message handling patterns. So we have the splitter pattern. So as a message comes in, you have a “split-on” property that’s on your trigger, for example. And it will actually look at the collection that gets passed in the message and create multiple instances of your Logic App based on that property path. So we will do that work for you. You can do your own split with the for each, and Derek will show you that a little bit later.
The claim check pattern. You don’t want in-messaging scenarios, you don’t want to pass big payloads as part of your messages in your queue. So the pattern that you use as a claim check, where your queue message has a reference to your item, for example, in a blob store. If you have a, you know, a 20-megabyte message, you don’t pass that in the queue, you pass a reference to it. And then you go ahead and pass that around and then we can pull only when we need it within the business process.
Data transformation enricher. So then, you know, you saw we have from the talk yesterday an Enterprise, the Enterprise integration capabilities, XML mapping, you know, JSON mapping, you can do object manipulation within Logic Apps, content-based router, right? You can look at the content, you know, as the message comes in, we make it really easy for you either to do an XPath to a particular field and your XML message or with JSON, you can use the first class set of tokens to then base that on a switch statement or some other criteria or push it to a topic and then let the topic do the work for you for content-based routing.
And then, you know, when you put all these things together, then you can do message pipelining, right? So the typical scenario is a vetter, so validate, enrich, extract, transform, enrich, and en route, right? All this is capable within Logic Apps.
As you do queuing, you want to be able to do scenarios where you want to have safe extraction of your messages from the queue. You don’t want to pull the message from the queue and delete it right away because then something may happen downstream, fail and now that message is lost. You can implement the peek-lock pattern and in Logic Apps, so that’s, for example, you have a service bus queue or topic, then you can, when that message arrives, we have a peek-lock pattern, and you can handle the message. And if something, if everything goes well, you complete it, if something goes wrong, you can either abandon it or put it into a dead-letter queue.
If you do long processing before you commit to completing the message or handling the message, you can extend the timeout on messages, there’s a default timeout in service bus. I forgot what the default timeout is, a few minutes. But you can go ahead, if you know that’s long, that’s going to be a long process, you can go ahead and extend that lock and then keep that message alive so it doesn’t get auto-abandoned for you.
Let’s do a peek-lock, and I’m going to put that in my handy dandy resource group. And I’ll pin that to the dashboard. Okay, so while this Logic App is being created, what I’m going to do is show you how you can do your peek-lock in Logic Apps using queues. Oh, I should pull out, [inaudible 00:21:35]. I get to use IOT. It’s like, “What? What does IOT have to do with messaging?” “Everything.” I see buttons. Okay. Now, everybody’s curious. What am I going to do with that button?
The first thing we want to do is go ahead and open service bus, so we’re going to do a one-way, some one-way messaging and in this case, I’m going to when a message received in a queue peek-lock, right? So I’m going to listen for a message in the queue and peek at that message and then it essentially locks it so nobody else can get to it. And they… We’ll go ahead and do my request queue. We’ve talked about, you don’t, you need to do an [inaudible 00:22:30] in 30 seconds.
Okay, so then what I want to do is I want to do some actions. I don’t know what I’m going to do yet, so I’ll just put a scope. It’s like, “There’s my actions,” and then finally I’m going to complete the message, and complete the message in a queue. Where you pick our queue, this is our request queue. And then finally the lock.
I just wanna pause here for a second. I just did a peek-lock scenario in Logic Apps in about 10 seconds. How long would that have taken you writing code?
Okay, so I’ve, you know, what we see here is the ability to go ahead and peek into the queue, do some magic work, and I’ll do something interesting in a second, and then complete that message, so the simplest scenario that you can think of.
But sometimes that stuff that you do fails or has an error so, you know, we talked about that try-catch-finally scenario, so what I’m going to do here is add a parallel step. I’m going to add an action, and again, this time in service bus, if something bad happens, I want to dead-letter it, right? There a couple, there are many different things you can do, but I’ll keep this simple which is dead-letter the message in a queue, okay?
I’m going to pick my request queue, and the lock token for that. But now, what I want to do is like, well, I don’t want to do both of these, I gotta choose one. So we go here to this… Let me do this for you guys. Hey, look at that? That’s bigger. Can you guys see in the back?
Kevin: All right. So I’m going to go ahead and configure the run-after. And so typically, we mark “is successful” for you, but this time instead of doing that, I want to do…if anything else happens besides being successful, please dead-letter this message. Done. Okay? Then what you’ll see is this red dot, dot, dot. So that you know that it’s under some different criteria that will run.
So this is my pattern for being able to do, you know, peek-lock and being able to dead-letter in case something goes wrong. Save that, everything works. Everybody’s happy, great. But let’s do something interesting.
I want to show you the parallelism within Logic Apps. I’ve got three minutes, okay. Parallelism, so let’s go ahead and send approval. What I’m going to do is for every message that comes in, this is not necessarily a realistic scenario, but I wanted to prove a point about how parallelism works in Logic Apps. So I’m going to send this to myself, and I will send the content of the body to me in email. And I’m going to add a condition that says, “If the selected option is approved…” That’s not what I wanna do. Zoom-in is really hard. Okay, there we go. I want to…if I’ve approved it, then I want to send it to the approval queue. So I’m going to hit call service bus again. Maybe I have zoomed in too much. Well, let’s see. We love zoom. Let’s zoom out a little bit, sorry, guys. There we go.
Okay, so I’m going to send this message to an approval queue and the content will be the contents of the original message that came in, and the… What’s that? Now you’re just going to send that content to that queue, and if it doesn’t work, right? If I reject it, then I want to send that message to a rejected queue. Hit send to rejected queue and then the content is my content, that’s it. Easy. Go ahead and save that. As a matter of fact, let’s make this, here’s a little tidbit for you, if you don’t like these names, change them. “Send to rejected queue.” Okay, go ahead and save that.
So now, what I’m going to do is I have, everything’s working correctly. I have already built a Logic App that will act as my… Where’s my Logic App? Oh, I see I’m on the wrong dashboard. Come on.
Man 4: [inaudible 00:27:51].
Kevin: Yeah, that’s okay. So I’m not going to go waste time on that. So I have a Logic App that will actually listen to this button and every time I click the button, it’s going to send a message to my request queue. So we can do IOT devices calling a Logic App to go do that. So let’s go and see. I have a service bus queue here, and I’m going to send two messages, okay? I click my button twice, and if I refresh fast enough, we should see two messages in the request queue, magic, okay? And then if I go back to my Logic App, what I’ll see, or I should see, is two instances running, right? So we talked about the parallelism of those Logic Apps. It’s sitting there waiting for me to approve these messages.
And I would have in my email, once this comes up, see, it’s waiting there, waiting for that approval message. If I go to my email, we’ll see that there are two approvals sitting in my inbox. I can go ahead and I’ll approve this one, and reject this one, and then we can see, going back here, that this one is completed, it went through the successful path. And then this one, if I did it right… Oh, I didn’t show you actually. Condition. This one went through the reject queue and this one went through the approved queue. Great. Parallelism.
So let’s go ahead and change it. I got to go a little faster. I’m going to change this so that, I’m going to change my levels of parallelization on this. So if I go to settings, there’s this great concurrency control. So if I turn that on, so you can see that you can go from 50 down to 1. So I want this to be a singleton, so I’m going to change that to one, done. Save. I go back to my handy dandy service bus helper, all right? See one in each of those queues, I don’t do this twice again. Two more messages have gone through, but this time, what you’ll see…all right, there’s two messages there…is that when I go back to my Logic App, I will, everything’s gone right, have only one pending, come on, one pending item that’s waiting for me. And so if I go to my email, this comes up. See, it’s pending. So if I bring this up, I’ll see this last approval, and once I approve it, this will go through, this will complete. And then we’ll see a second instance come up. A second instance come up, come on.
Anticipation, I know it’s there. Hello? Believe me? Yes, I know you guys believe me. It’s there. Come on, there it is. Then there’s a second one. So this is, you know, showing that you can do in-order processing or making sure that you handle only one message at a time, so now this is a new message, now it’s sitting in my inbox. And if I let this sit here for a while, it’ll actually time out, and we’ll go back into the queue, and then we’ll fail if I try to complete this message because that’s how timeouts work on messages. So that’s it. I’m going to reject that one.
So what I’ve shown you is the ability to do tries in your try scope, and then if something fails, to go ahead and dead-letter a message in the queue, and do parallelism within Logic Apps.
So, in-order processing. If you want to use, do in-order processing, keep in mind that you have to use a transport that supports in-order processing, service buses are great transport for that. Use singleton workflows, if the workflow has to be in the singleton mode because we instinctively run in parallel. Remove parallelism for for each.
If you have a for each statement in your Logic App, and you want the sequential pattern, make sure that you turn that off and Derek will show you that, as well, and we can also do sequential convoys. So sequential convoys would be would be done in Logic Apps using service bus sessions. So those sessions, everybody know what a sequential convoy is? You all BizTalk guys, right? Yeah, some of you guys, the old guys know.
Sequential convoy is the ability to have a convoy, right? A series of convoys of messages that go in order to your destination. For example, I used that hospital scenario. Bob goes to the hospital and he has 10 messages about him getting checked in, getting his blood taken, getting a bed, etc., but all those messages happen and get mixed up in a queue. If you use sessions and you listened to that session called Bob, you will only get Bob’s messages and they will be in order in that session. So you can you can enable that in Logic Apps, as well. That’s it. I want to give Derek his opportunity to do “Best Practices.” All right.
Derek: Let’s switch gear a little bit and talk about best practices when you work on your Logic App. Now these are brand new contents that were prepared specifically for you and they have never been shown before, so hopefully, you will like it. Let’s start with variables. Variables are quite helpful and useful in Logic App, but there are a few things you should keep in mind when using them. First is that variables in Logic Apps, they are all global variables. Meaning they have to be declared initialized at the root level, they cannot happens in a scope, in a condition, there are reasons for it. And there are workarounds that you can do to work around the limitation, and we’ll get into it very shortly.
The second is array is heterogeneous. Meaning, if you have an array variable, you can have different types of objects in the array. We do not enforce a schema, nor do we do validation when you append to the array. So you can, technically, have an array with some integers, with some Boolean values, with some nested arrays. It’s up to you to determine if that’s the best course of action for your scenario. But we do not block you from doing those thing.
Lastly, care needs to be taken when you use variables within the for each loop. Like Kevin have mentioned, for each loop by default runs in parallel. We run up to 20 instances by default for for each loop, and it can be configured from anywhere between 1 to 50. So something that you do may not give you the expected results. Referencing the variable is perfectly fine, if you want to increment and decrement the variable, that’s perfectly fine to do in a default for each loop that runs in parallel. Setting a variable most likely will not work and will not give you the expected result. And appending to a [inaudible 00:35:12], depending on what you are expecting, it may or may not work.
So what do I mean by that? Let’s switch to the demo really quick. So here I have a Logic App where I simply initialize an array variable. I don’t have any initial content, and in a for each loop, I’m using this range expression to loop it over for 10 times.
I’m going to just add an action called append to array. So I’m going to append the current item to this array variable. I’m just going to select my array variable here, and they’re going to choose the current item, that’s the value that I’m appending to it. After the for each, I’m just going to use a compose to print out the value so we can examine it in the run history view.
So I’m going to select compose, and I’m going to choose the variable as the input. So let’s save that and see what happened. Normally, you would expect an array that you get from running this particular Logic App to start from zero and goes all the way up to nine, would that be the case? We’ll take a few seconds to run the for each loop.
If we open the compose card, you will see the numbers are actually inserted out of order. Again, if you think about how Logic App executes your parallels and how it executes your for each loops, it makes sense because we run all 10 iterations at the same time, and any particular iteration may complete, resulting in the value to be inserted at a random order.
So how do we fix that? What if you do want this array to be in an ascending order? Let’s switch back to designer, we’ll go into the settings page for this for each action. We’ll turn on concurrency control. You will see by default it is set to 20, like we previously mentioned, I’m just going to put this slider all the way down to one. Meaning, I want to run this for each loop in a sequential fashion. So I’m going to save the Logic App and just run this. I didn’t change anything except how I want the for each loop to execute. Now, once this run is complete and we can exam the compose output, if everything goes as planned, we should see these values showing in an ascending order.
Something you have to consider when building your Logic App and when consuming variables and when working with for each loops, sequential for each comes in handy when you want this in-order behavior.
Since we’re talking about arrays, I thought we would just expand this a little more. So working with arrays. Logic App make it quite easy for you to work with arrays: we give you tokens, we add implicit for each for you when you reference a particular object or property within that array. Well, let’s pick a particular example. So we have been using orders, for [inaudible 00:38:04] retail. Let’s say we receive a batch order of 10,000 items, and we want to do some business logic on top of this particular array. We say, let’s say if the order is greater than $10,000, we want to access this on business logic, we want to send some approval. But about 10% of those orders will meet this criteria. So, out of the 10,000, we’ll probably have a thousand of those orders in which we want to run this approval.
How do you do it? Normally, so let me switch back to another Logic App in which I already have the schema prepared. Normally, you would start with a for each loop, you would say, “For my for each loop, I’m going to loop over the array,” in which case is the body of my request. Inside for each, I’m going to use a condition. I’m going to say the amount which is the one that I care about is greater than a thousand, right? So if that is the criteria, it meets it, it matches the criteria, if it’s true, I’m going to do something. I’m just going to use compose an as example, so this is our do something action.
This is what most people would do, but if you think about it, is there another way that we can make this better both for performance and for cost? Instead of doing it for each, and then a condition, we can actually tweak this just a little bit. I’m going to use a filter array instead. Filter array is a single action that takes an array as input and allow me to get a new array based on the filtering criteria that I’m looking for. So in this case, I’m saying, “I want to filter the body array which is coming from the trigger, I’m going to filter it down to only those that has an order amount greater than a thousand.” Once I have the filtered array, then I can use a for each loop, and they can loop over the new array and do my business logic on top of it.
So what’s the difference? Well, let’s compare. The first operation, we would incur one billable event for the for each action, but the condition will actually execute 10,000 times because we have an array of size 10,000 that we loop over. Only 10% of those will meet the condition criteria that we defined, so we’ll actually execute a compose in which we use to demonstrate the business logic a thousand times, which will result in a total of 11,001 billable action.
The second option though, we incur one billable event for the filter array, we do one billable event for the for each, but we only have to do a thousand action, which in total is only 1,002. So that’s 10X difference. We tweaked the Logic App just a little bit and we lower the cost 10 times fold. So this is this is quite cool, I think. And it’s something that you should consider depending on scenario, depending on the array, the kind of things that you, the kind of day that you’re working with, there are ways that you can optimize to save cost.
But is there another way? Instead of doing the for each here, the other option is to call a child’s Logic App. So instead of doing the for each, I’m going to call into a child Logic App. I think we call it a child Logic App Demo. So here, we’re going to pass in the filtered array as the input. So what are we doing here? Instead of looping over the array, we’re actually passing down the filtered array to a child Logic App. And in the child Logic App, if I switch to that, we can then put a split down on the trigger. So we’ll say, we want to split on the input array, and execute my business logic.
So let me switch back to the deck, then let’s take a look at the comparison. The third option is actually 11 more expensive, right? If you look if you do the math, we’ll do one for filter array, one for each, one to call the child Logic App, the split-on trigger will incur additional 1,001 billable actions and everything else remains the same.
It’s twice as expensive as the second option, but there are some distinct advantage to it. We talk about variables being global scope within Logic App, but by putting the, but by calling the child Logic App, I can actually have a variable in my child Logic App that is localized to the current item that I process in those. So this is the workaround that I mentioned. If I want to have a local variable for the current iteration, this is how I can do that.
The other thing that I want to mention is there is actually a performance difference between the two option. If you think about it, what do we do for for each? We actually run multiple iterations in parallel, we do 20 by default and you can increase it to 50, but still, there is a limit. If I have a thousand items, I can do only 50 at a time. Then we have to wait for all the iterations to complete, and then we aggregate the results so we know what is the terminal status from a for each action and then any action after that can be executed depending on their run-after status. So that’s the overhead I incur by doing for each.
When calling a child Logic App, there’s really no upper limit on how many child Logic App that can spin up with a split-on trigger. So when I pass in an array of a thousand items, I can actually create a thousand child Logic App running instance all happening at the same time.
The parent Logic App is also fire-and-forget. The Logic App is simple, they have to call the child Logic App, passing the array and be done with it, we don’t have to wait for it to complete. Which means there’s no aggregation of the data from all the instance, and which makes the parent Logic App also runs faster.
So again, it’s always a trade-off, is how much do you want to spend and what is the performance target that you are aiming at? We talk about cost estimation, then we have been looking at those tables. If you remember about a year ago, this is kind of the form that you have to do to figure out how much your Logic App will cost you. It’s really complicated. We have made it much simpler. It’s really three bullet points that I think about when estimating cost. Trigger evaluation cost money and action execution cost money, retry counts, as well.
We’ll only charged if the status is succeeded or failed. That means number of action that I see in the designer doesn’t necessarily equals to the action that I will be billed when I trigger a run. Think about it. If I have a condition, and I have two action in each of the branch, only one branch will execute for any particular run. That means I will only be billed for two actions instead of four.
So these are the things that you should take into consideration. Similarly, run-afters, right? If we have something that ran after failure, and we didn’t, we didn’t run into an error scenario, I’m not going to be charged for those actions because they will be skipped. Then we have three different tiers of actions. We have built-in, we have connectors, and then we have Enterprise connectors. They are priced differently. Now, the question that we hear from many people is, “How can I figure out how much a particular action will cost and how can I tell whether it’s a built-in action or whether it’s a connector or Enterprise connector?
We have listened to your feedback, and we are working on a UI refreshment, you have seen a sneak peek from Kevin’s demo previously. So this is the new search experience that we’re working on and will be available very soon. The change we’re making here is we’re breaking up different types of actions into a few buckets or pivots.
So we still have the all view for you to browse and see the 200-plus different connectors that Logic Apps give you in one unified view, but then you can also browse only the connectors, Enterprise connectors, built-in or even your custom connector ones. We’re making this very easy for you to find the things you are looking for and know where they belong.
And this is also a good starting point, it’s a good canvas for us to start adding more stuff to it. You have been asking us to be more smart in helping you build integration solutions, making smart recommendations on what actions to use next, “Give me the things that I just use,” “Allow me to favorite things that I want to see all the time.” This is the place that we can enable those scenarios for you.
So I think that’s the demo, and I hope you like it. And like I said, and like we have mentioned previously, if you have any feedback in the design of this, anything that you want to see, go to our User Voice Page, go to our Twitter, and let us know what you think and what you want us to be working on next. Thank you very much.
Fill the form below to get all the presentations delivered as a single zip file in your mailbox.
byJon Fancey & Matt Farmer
byMicrosoft Integration Team