8 Mei 2022

Spider Workflow in Action

After my previous post about the conception of the spider workflow, let’s put this into action. Let’s think about multi-level of approvals that you might have in your requirement.

Let’s imagine we have this simple requirement for a workflow in Power Automate, and we need to express the logic in Power Automate using the spider workflow concept. First of all, let’s work the trigger header, because we might need some of the information in it especially which account triggered the workflow.

Next, let’s work on the variables. Like previously mentioned, we need a boolean variable which will be the stopper of the workflow just like a cork of your wine bottle. Next is the entire workflow configuration just like I have shown you earlier (read the previous post for more) but with a little twist.

If you want a quick escape, just copy and paste the following code below.



[
  {
    "Index": 1,
    "Stage": "Review",
    "Status": "Pending Project Admin Review",
    "Type": "CustomApproval",
    "Approval": {
      "Actions": [
        "Checked",
        "Return"
      ]
    },
    "SendAttachment": true,
    "AssignedTo": {
      "AssignmentType": "Custom",
      "Assignee": [
        "radityo.ardi@radityoardidev.onmicrosoft.com"
      ]
    },
    "Outcomes": [
      {
        "Outcome": "Checked",
        "Next Index": 2
      },
      {
        "Outcome": "Return",
        "Next Index": 7
      }
    ]
  },
  {
    "Index": 2,
    "Stage": "Approval 1",
    "Status": "Pending Approver 1",
    "Type": "BasicApproval",
    "SendAttachment": true,
    "AssignedTo": {
      "AssignmentType": "Custom",
      "Assignee": [
        "radityo.ardi@radityoardidev.onmicrosoft.com"
      ]
    },
    "Outcomes": [
      {
        "Outcome": "Approve",
        "Next Index": 3
      },
      {
        "Outcome": "Reject",
        "Next Index": 6
      }
    ]
  },
  {
    "Index": 3,
    "Stage": "Approval 2",
    "Status": "Pending Approver 2",
    "Type": "BasicApproval",
    "SendAttachment": true,
    "AssignedTo": {
      "AssignmentType": "Custom",
      "Assignee": [
        "radityo.ardi@radityoardidev.onmicrosoft.com"
      ]
    },
    "Outcomes": [
      {
        "Outcome": "Approve",
        "Next Index": 4
      },
      {
        "Outcome": "Reject",
        "Next Index": 6
      }
    ]
  },
  {
    "Index": 4,
    "Stage": "Super Admin",
    "Status": "Pending Super Admin",
    "Type": "CustomApproval",
    "Approval": {
      "ApprovalType": "customresponse",
      "Actions": [
        "Complete Request",
        "Return"
      ]
    },
    "SendAttachment": true,
    "AssignedTo": {
      "AssignmentType": "Custom",
      "Assignee": [
        "radityo.ardi@radityoardidev.onmicrosoft.com"
      ]
    },
    "Outcomes": [
      {
        "Outcome": "Complete Request",
        "Next Index": 5
      },
      {
        "Outcome": "Return",
        "Next Index": 7
      }
    ]
  },
  {
    "Index": 5,
    "Stage": "Closed",
    "Status": "Completed",
    "Type": "Closure"
  },
  {
    "Index": 6,
    "Stage": "Closed",
    "Status": "Rejected",
    "Type": "Closure"
  },
  {
    "Index": 7,
    "Stage": "Resubmission",
    "Status": "Pending Resubmission",
    "Type": "Closure",
    "SendAttachment": true
  }
]


Next up, is to parse the JSON configuration well enough so that it’ll save time when you want to reference a specific JSON object property. And the subsequent action is to initialize the first index we need to tag as the first entry of the stages.

Just for your own sake, Index is just one idea to ID the current workflow stage. In the real world, you can use string, GUID, text, numbers, or anything that can identify what is the current stage and it has to be unique.

Now, here’s the heart of the spider workflow. We can’t use a state, pointer, go-to, or something like that in Power Automate to make the flow goes back to the controller. To overcome, we use Do-Until action until the [Keep Looping] variable turns false. You need the [Stop the loop] in case of any error or time out, so it doesn’t go to endless loop. Optionally, you can get the controller’s error message.

[Stop the loop] basically just to set [Keep Looping] to false.

Inside the controller, you probably need to find what is the current stage from the configuration. The next step up, is to filter the parsed body of the entire configuration that come out from [Parse Flow Configuration] action. This is where it gets interesting, you have to filter where the [Index] is equal to [Stage Index] which is 1. Then, parse the JSON value simply by taking the body of [Filter Flow Configuration on Index] which will return an array and take the first one.

Parsing the JSON is always helpful especially when you want to work the flow quickly without doing too many trial-and-error.

But then the next action is just simply notify the requestor what’s the current stage coming up. It’ll be just a message saying “Hi requestor, your flow now is in ___ stage with status of ____”. Simple enough…

Then, you [Switch on Type] that will be the path of your next bus stop of your flow. In this case, we identify 3 different types based on the configuration: BasicApproval, CustomApproval, and Closure. We can put [Closure] under [Default] which makes the logic more broad as if like “if the type is either Closure or everything else, then stop the loop”. Let’s take a closer look how the routing done on approval side.

Now you clearly see, that we’re going to filter the [Outcomes] array where [Outcome] property is equal to the outcome of the flow and return what’s the [Next Index] of that outcome and assign back to the [Stage Index]. Eventually, the loop will be executed once again to see whether it’s the Closure or another step of approval.

No bluff, that’s it!

Last words

Now, all I can say is just congratulations that you now can work with any kind of approval flow. Your stakeholder asks for more approval? No problem, give ‘em that!

But just don’t be too happy first and hear me out. If your workflow configuration is salty, the entire workflow may go ugly too. So, make sure you have done your thought process while thinking out loud what’d be the configuration for this flow.

via GIPHY

5 Mei 2022

Implementing Spider Workflow in Power Automate

There are many patterns to implement different types of workflow using Power Automate. But one that strikes me a lot in terms of the dynamicity, is the spider workflow. There are not much of reference out there, it was (in my work history) implemented in a project in one of the prestigious client in Singapore, sparked by my technical architect.

Drawing1

It’s called spider because… of course it looks like a spider. This pattern can be repeated in many projects and even one can implement the template for it in Power Automate. This pattern mainly to overcome a problem when the workflow is not well-defined, prone to change, or to provide dynamic ever-changing workflow without re-work of the entire workflow.

Implementing Spider Workflow

The main concept of this workflow is to loop the process back to the controller after the decision of the next path. The first step to work this out, is to define how many distinctive tasks that a process can do. In the sample diagram above, there are 5 paths that goes everywhere with one of them proceed to end the workflow. The other four, goes back to the controller to decide what’s the next path after an outcome is reached. In the real-world, it can spawn more than 5 or less, depending on the requirement.

The second step, you need to run your thought process to link up between an outcome with the next path. To give you an example, if say the initial flow goes to Approval first (Path 1), definitely it will have 2 outcomes whether it’s Approve or Reject. You could make a story where after the first approval, it will go to another level of approval if the outcome is Approve (Path 1). Otherwise if it’s Reject, you then decide to flow it to End the workflow (Path 3). If you get the feel of your own thought process thoroughly, you could end up having the exact same flow like in the diagram below.

Drawing2

Now, how do we take care of the workflow’s most important mechanism such as notifying the requestor or setting the workflow status once it’s completing one stage? These mechanism you actually can put under the controller itself since it’s executed every time it passes with another path decision.

Be very careful when you run your thought process, do avoid any process that potentially goes into an endless loop (because it can happen). The design itself is perfect, this endless loop can happen due to misconfiguration. Wait, there’s configuration?

Spider Workflow Configuration

There is a configuration to accompany this flow. You could actually leverage on anything to store, literally. Back in my old days, all workflow data are stored as a row in a SQL Server database. Nowadays, you can just work out the JSON configuration and let the configuration be parsed by the flow. Let’s take a sample on how you can define the JSON structure for just one single stage.


{
	"Index": 2,
	"Stage": "Approval 1",
	"Status": "Pending Approver 1",
	"Type": "BasicApproval",
	"SendAttachment": true,
	"AssignedTo": "Dynamic",
	"Outcomes": [
		{
			"Outcome": "Approve",
			"Next Index": 3
		},
		{
			"Outcome": "Reject",
			"Next Index": 6
		}
	]
}

As above is just a simple sample, you could define your own JSON that depicts the flow process. To summarize,

  • Index – defines the index of this current path.
  • Stage – defines the current stage name (or whatever you want to define as the state of the current flow).
  • Status – defines the workflow status for the current path.
  • Type – defines the path where to go. If you could link this up with the first diagram above, it’s the Path 1.
  • SendAttachment – typically the current controller’s configuration to send attachment to the approver. You can also add your own other configuration.
  • AssignedTo – is also the current controller’s configuration to take the approver list dynamically from a table or database. The other values can also be “Requestor” where it will assign to the initiator of the flow.
  • Outcomes – defines the routing! You can read it simply by say if the outcome is “Approve”, go to the object that the index is 3. Else if it’s “Reject”, go to index 6.

Now, if you run your thought process, you could define a JSON configuration for the entire process just like below.


[
  {
    "Index": 0,
    "Stage": "Resubmission",
    "Status": "Pending Resubmission",
    "Type": "Closure",
    "SendAttachment": true,
    "AssignedTo": "Requestor"
  },
  {
    "Index": 1,
    "Stage": "Review",
    "Status": "Pending Project Admin Review",
    "Type": "CustomApproval",
    "SendAttachment": true,
    "Actions": [
      "Checked",
      "Return"
    ],
    "AssignedTo": "Dynamic",
    "Outcomes": [
      {
        "Outcome": "Checked",
        "Next Index": 2
      },
      {
        "Outcome": "Return",
        "Next Index": 0
      }
    ]
  },
  {
    "Index": 2,
    "Stage": "Approval 1",
    "Status": "Pending Approver 1",
    "Type": "BasicApproval",
    "SendAttachment": true,
    "AssignedTo": "Dynamic",
    "Outcomes": [
      {
        "Outcome": "Approve",
        "Next Index": 3
      },
      {
        "Outcome": "Reject",
        "Next Index": 6
      }
    ]
  },
  {
    "Index": 3,
    "Stage": "Approval 2",
    "Status": "Pending Approver 2",
    "Type": "BasicApproval",
    "SendAttachment": true,
    "AssignedTo": "Dynamic",
    "Outcomes": [
      {
        "Outcome": "Approve",
        "Next Index": 4
      },
      {
        "Outcome": "Reject",
        "Next Index": 6
      }
    ]
  },
  {
    "Index": 4,
    "Stage": "Super Admin",
    "Status": "Pending Super Admin",
    "Type": "CustomApproval",
    "SendAttachment": true,
    "Actions": [
      "Complete Request"
    ],
    "AssignedTo": "Dynamic",
    "Outcomes": [
      {
        "Outcome": "Complete Request",
        "Next Index": 5
      }
    ]
  },
  {
    "Index": 5,
    "Stage": "Closed",
    "Status": "Completed",
    "Type": "Closure"
  },
  {
    "Index": 6,
    "Stage": "Closed",
    "Status": "Rejected",
    "Type": "Closure"
  }
]


Lastly, this blog is just a conceptual idea that you can implement in each project you go on either with Nintex, Power Automate, K2, or any other cloud workflow out there.