- When a Communication site or an Office 365 Group connected Team site is created, a Site Design gets applied to it.
- The Site Design contains a triggerFlow action which starts a Microsoft Flow (configured to be triggered by an http request).
- The flow adds an item to an Azure storage queue which triggers and Azure Function.
- The Azure Function contains the PnP template and the code to apply the template to the newly created site.
This approach is described in the guidance here: Calling the PnP provisioning engine from a site script
Now the problem with this sequence of actions is that (as of this time) they are all Asynchronous events i.e. "fire and forget". When the Site Design executes the triggerFlow action, it does not wait for the Flow to complete before showing the success screen to the user. Similarly, after the Flow adds an item to the storage queue, quite understandably, it does not wait for the triggered Azure Function to finish executing before completing its run.
In this sequence of async events, if we want to perform an action like sending a notification email after the provisioning is complete, we have the following options:
Multiple Flows:
Use an output storage queue and in the Azure Function, add an item to it when the provisioning completes. Have another Flow triggered by the output queue, which sends the email. I am not a big fan of this approach as this means managing an output queue as well as a second Flow just for sending the email notification.
Polling:
If we want to avoid creating a second Flow, another option is to use a Do Until action and poll for when messages arrive on the queue. The main drawback of this approach is that we must keep track of different instances of the Flow. If multiple users are creating sites and there are multiple messages arriving on the queue, we want to send the email only after the message of our own site arrives. This is doable using the Flow instance id but a bit too complex for my liking :)The solution: HTTP Webhook
Fortunately, there is a nice way to handle this. Using the HTTP Webhook action, we can basically wait for the provisioning to complete before returning the control back to the Flow. Since we are in a serverless world here, the Flow will essentially pause here and "wake up" when we want it to.To use this approach, we have to make a slight modification to the approach suggested in the Microsoft documentation. In this approach, instead of firing the Azure Function with a queue trigger, we will fire it using the HTTP Webhook action. The Function will be configured to execute on HTTP trigger i.e. when an HTTP request is made to an endpoint.
Here is an overview of actions for the Flow:
The Flow starts when the Site Design executes the triggerFlow action:
Here is the code for the Azure Function:
Now, it is only matter of parsing the data returned from the Azure function and sending the email:
This way, we can perform actions in the Flow after the PnP template has been successfully applied to the site.
Hope this was helpful!
4 comments:
Are there any disadvantages to doing away with the storage queue in regards to how the Azure Function is initiated? I love this approach but wasn't sure if there would be any drawbacks to no longer having a queue in play.
I don't see any sequencing reasons for retaining the queue (i.e. site 1 is processed before site 2), but wondered about reliability in cases where for instance 10 sites for created in tandem. Thoughts?
Hi Patrick, there has been some good discussion on this topic here: https://twitter.com/vrdmn/status/958358018575433728
If you feel that queues provide a more robust design, another approach you can take is keep using a queue but then add a message to the queue from the Azure function instead of adding it from the Flow. See the http webhook section in this post: https://medium.com/@jeffhollan/calling-long-running-functions-from-logic-apps-6d7ba5044701
Hi Vardhaman,
I have a kind of security question.
Is there a way how to ensure inside of the azure function, that it is called only from the certain tenant flow?
I'm trying to implement this for a client, I think I missed where the callback URL comes from? Is it the url from the HTTP trigger action? If so, is there a way to do this while using a PowerApps trigger action? I'd like to not have to create a second Flow if possible.
Post a Comment