Switch States Conditionally in a Flow

This procedure demonstrates how to implement a multi-state flow.

This sample code shows how to design a flow that checks for a resource and updates it. If the resource doesn't exist, the flow creates a new resource.
  1. Open the adapter definition document in Visual Studio Code.
  2. In the flows code section of the document, add code for a flow with GET call to a specific resource.

    In the following code sample, the httpInvoke function implements the GET call.

    "flows": {   
       "EventRegisterFlow": {
          "id": "EventRegisterFlow",
          "description": "EventRegisterFlow",
          "specVersion": "0.8",
          "version": "0.1",
          "start": "startState",
          "functions": [
            {
              "name": "httpInvoke",
              "type": "custom",
              "operation": "connectivity::rest"
            }
          ],
          "states": [
            {
              "name": "startState",
              "type": "operation",
              "actions": [
                {
                  "name": "httpInvoke",
                  "functionRef": {
                    "refName": "retriveListOfSubscriptionFunc",
                    "arguments": {
                      "uri": "${\"https:/\"+\"/\"+.connectionProperties.hostNameTrigger+\"/repos/{owner}/{repo}/hooks\"}",
                      "method": "GET",
                      "parameters": {
                        "owner": "${ .configuration.orgId }",
                        "repo": "${ .configuration.repositoryId }"
                      }
                    }
                  },
                  "actionDataFilter": {
                    "results": "${ .body}",
                    "toStateData": "${ .subscriptions }"
                  }
                }
              ],
              "end": true
            }
             
        }
  3. Add actions to the flow to evaluate if a specific resource exists.

    Sample code:

    "functions": [
      ...
      {
        "name": "SubscriptionExistsFunction",
        "operation": "[.integrationProperties.INTEGRATION_FLOW_URL==.subscriptions[].config.url]|any",
        "type": "expression"
      },
      {
        "name": "getSubscriptionId",
        "type": "expression",
        "operation": "[{subscription:.subscriptions[], INTEGRATION_FLOW_URL:.integrationProperties.INTEGRATION_FLOW_URL}] | map(select(.subscription.config.url==.INTEGRATION_FLOW_URL))[0].subscription.id | tostring"
      }
    ],
    "states": [
      {
        "name": "startState",
        "type": "operation",
        "actions": [
          ...
          {
            "functionRef": "SubscriptionExistsFunction",
            "actionDataFilter": {
              "toStateData": "${ .subscriptionExists }"
            }
          },
          {
            "functionRef": "getSubscriptionId",
            "actionDataFilter": {
              "toStateData": "${ .subscriptionId }"
            }
          }
        ],
        end: true
      }
  4. Add a switch state to transition to another state that can create or register a resource.

    Sample code:

    "flows": {   
       "EventRegisterFlow": {
          "id": "EventRegisterFlow",
          "description": "EventRegisterFlow",
          "specVersion": "0.8",
          "version": "0.1",
          "start": "startState",
          "functions": [
            ...
          ],
          "states": [
            {
              "name": "startState",
              "type": "operation",
              "actions": [
                ...
              ],
               
              "transition": "SwitchBasedOnSubscription"
          
            },
            {
              "name": "SwitchBasedOnSubscription",
              "type": "switch",
              "dataConditions": [
                {
                  "condition": "${ .subscriptionExists == true }",
                  "transition": "UpdateRepositoryEndpoint"
                },
                {
                  "condition": "${ .subscriptionExists == false }",
                  "transition": "RegisterRepositoryEvent"
                }
              ],
              "defaultCondition": {
                "transition": "RegisterRepositoryEvent"
              }
            },
             
    }
  5. Add termination states that branch from a switch.

    The termination states contain the required actions.

    Sample code:

    "flows": {   
       "EventRegisterFlow": {
          "id": "EventRegisterFlow",
          "description": "EventRegisterFlow",
          "specVersion": "0.8",
          "version": "0.1",
          "start": "startState",
          "functions": [
           ...
          ],
          "states": [
            {
              "name": "startState",
              "type": "operation",
              "actions": [
                ...
              ],
              "transition": "SwitchBasedOnSubscription"
            },
            {
              "name": "SwitchBasedOnSubscription",
              "type": "switch",
              "dataConditions": [
                {
                  "condition": "${ .subscriptionExists == true }",
                  "transition": "UpdateRepositoryEndpoint"
                },
                {
                  "condition": "${ .subscriptionExists == false }",
                  "transition": "RegisterRepositoryEvent"
                }
              ],
              "defaultCondition": {
                "transition": "RegisterRepositoryEvent"
              }
            },
            {
              "name": "UpdateRepositoryEndpoint",
              "type": "operation",
              "actions": [
                {
                  "name": "UpdateRepositoryEnpointAction",
                  "functionRef": {
                    "refName": "httpInvoke",
                    "arguments": {
                      "uri": "${\"https:/\"+\"/\"+.connectionProperties.hostNameTrigger+\"/repos/{owner}/{repo}/hooks/{subscriptionId}\"}",
                      "parameters": {
                        "owner": "${ .configuration.orgId }",
                        "repo": "${ .configuration.repositoryId }"
                        "subscriptionId": "${ .subscriptionId }"
                      },
                      "method": "POST",
                      "body": "${ { \"name\": \"web\", \"active\": true, \"events\": [.configuration.eventName] } }"
                    }
                  },
                  "actionDataFilter": {
                    "results": "${.body}",
                    "toStateData": "${ .output }"
                  },
                  "condition": "${ .subscriptionExists==true }"
                }
              ],
              "end": true
            },
            {
              "name": "RegisterRepositoryEvent",
              "type": "operation",
              "actions": [
                {
                   "name": "RepositoryEventRegisterAction",
                   "functionRef": {
                    "refName": "httpInvoke",
                    "arguments": {
                      "uri": "${\"https:/\"+\"/\"+.connectionProperties.hostNameTrigger+\"/repos/{owner}/{repo}/hooks\"}",
                      "parameters": {
                        "owner": "${ .configuration.orgId }",
                        "repo": "${ .configuration.repositoryId }"
                        "subscriptionId": "${ .subscriptionId }"
                      },
                      "method": "POST",
                      "body": "${ { \"name\": \"web\", \"active\": true, \"events\": [.configuration.eventName], \"config\": { \"content_type\": \"json\", \"secret\": .connectionProperties.\"trigger.secret\", \"url\": .integrationProperties.INTEGRATION_FLOW_URL } } }"
                    }
                  },
                  "actionDataFilter": {
                    "results": "${.body}",
                    "toStateData": "${ .output }"
                  },
                  "condition": "${ .subscriptionExists==false }"
                }
              ],
              "end": true
            }
          ]
        },
    }

    Complete sample code:

    "flows": {    
       "EventRegisterFlow": {
          "id": "EventRegisterFlow",
          "description": "EventRegisterFlow",
          "specVersion": "0.8",
          "version": "0.1",
          "start": "startState",
          "functions": [
            {
              "name": "httpInvoke",
              "type": "custom",
              "operation": "connectivity::rest"
            },
            {
              "name": "SubscriptionExistsFunction",
              "operation": "[.integrationProperties.INTEGRATION_FLOW_URL==.subscriptions[].config.url]|any",
              "type": "expression"
            },
            {
              "name": "getSubscriptionId",
              "type": "expression",
              "operation": "[{subscription:.subscriptions[], INTEGRATION_FLOW_URL:.integrationProperties.INTEGRATION_FLOW_URL}] | map(select(.subscription.config.url==.INTEGRATION_FLOW_URL))[0].subscription.id | tostring"
            }
          ],
          "states": [
            {
              "name": "startState",
              "type": "operation",
              "actions": [
                {
                  "name": "httpInvoke",
                  "functionRef": {
                    "refName": "retriveListOfSubscriptionFunc",
                    "arguments": {
                      "uri": "${\"https:/\"+\"/\"+.connectionProperties.hostNameTrigger+\"/repos/{owner}/{repo}/hooks\"}",
                      "method": "GET",
                      "parameters": {
                        "owner": "${ .configuration.orgId }",
                        "repo": "${ .configuration.repositoryId }"
                      }
                    }
                  },
                  "actionDataFilter": {
                    "results": "${ .body}",
                    "toStateData": "${ .subscriptions }"
                  }
                },
                {
                  "functionRef": "SubscriptionExistsFunction",
                  "actionDataFilter": {
                    "toStateData": "${ .subscriptionExists }"
                  }
                },
                {
                  "functionRef": "getSubscriptionId",
                  "actionDataFilter": {
                    "toStateData": "${ .subscriptionId }"
                  }
                }
              ],
              "transition": "SwitchBasedOnSubscription"
            },
            {
              "name": "SwitchBasedOnSubscription",
              "type": "switch",
              "dataConditions": [
                {
                  "condition": "${ .subscriptionExists == true }",
                  "transition": "UpdateRepositoryEndpoint"
                },
                {
                  "condition": "${ .subscriptionExists == false }",
                  "transition": "RegisterRepositoryEvent"
                }
              ],
              "defaultCondition": {
                "transition": "RegisterRepositoryEvent"
              }
            },
            {
              "name": "UpdateRepositoryEndpoint",
              "type": "operation",
              "actions": [
                {
                  "name": "UpdateRepositoryEnpointAction",
                  "functionRef": {
                    "refName": "httpInvoke",
                    "arguments": {
                      "uri": "${\"https:/\"+\"/\"+.connectionProperties.hostNameTrigger+\"/repos/{owner}/{repo}/hooks/{subscriptionId}\"}",
                      "parameters": {
                        "owner": "${ .configuration.orgId }",
                        "repo": "${ .configuration.repositoryId }"
                        "subscriptionId": "${ .subscriptionId }"
                      },
                      "method": "POST",
                      "body": "${ { \"name\": \"web\", \"active\": true, \"events\": [.configuration.eventName] } }"
                    }
                  },
                  "actionDataFilter": {
                    "results": "${.body}",
                    "toStateData": "${ .output }"
                  },
                  "condition": "${ .subscriptionExists==true }"
                }
              ],
              "end": true
            },
            {
              "name": "RegisterRepositoryEvent",
              "type": "operation",
              "actions": [
                {
                   "name": "RepositoryEventRegisterAction",
                   "functionRef": {
                    "refName": "httpInvoke",
                    "arguments": {
                      "uri": "${\"https:/\"+\"/\"+.connectionProperties.hostNameTrigger+\"/repos/{owner}/{repo}/hooks\"}",
                      "parameters": {
                        "owner": "${ .configuration.orgId }",
                        "repo": "${ .configuration.repositoryId }"
                        "subscriptionId": "${ .subscriptionId }"
                      },
                      "method": "POST",
                      "body": "${ { \"name\": \"web\", \"active\": true, \"events\": [.configuration.eventName], \"config\": { \"content_type\": \"json\", \"secret\": .connectionProperties.\"trigger.secret\", \"url\": .integrationProperties.INTEGRATION_FLOW_URL } } }"
                    }
                  },
                  "actionDataFilter": {
                    "results": "${.body}",
                    "toStateData": "${ .output }"
                  },
                  "condition": "${ .subscriptionExists==false }"
                }
              ],
              "end": true
            }
          ]
        },
    }