0

I have an elsa workflow parent which is calling some child workflows. Every child workflow has some custom activities (based on SendHttpRequest elsa activity). These custom activities need to call an external api and provide the workflowInstanceId of parent workflow.

I tried to pass the workflowInstanceId of parent as ContextId of child workflow – not working since is overridden inside of child workflow custom activity (which makes sense of course).

How could I get (server-side) the workflowInstanceId of parent workflow from a piece of code which is running on a child workflow (let’s say from OnExecuteAsync(ActivityExecutionContext context) of child workflow custom activity)?

Octavian
  • 15
  • 2
  • I also tried to set `Custom Attributes` from `Run Child Workflow` with `workflowInstacenId` of parent workflow but don't know how to get these values on server side. – Octavian Apr 07 '22 at 17:07

1 Answers1

1

Although Elsa 2 (2.6 at the time of writing) does not have a real notion of parent-child workflows (i.e. workflows invoked by other workflows do not have any reference to their parent), you can use the RunWorkflow activity to provide arbitrary input to the child workflow. Including its own workflow instance ID.

For example, use the following JS expression on the RunWorkflow activity to send the workflow instance to the child workflow:

({ parentWorkflowInstanceId: workflowInstanceId })

Then, from your child workflow, your first activity should be the one to capture this value, e.g. using a SetVariable activity:

input.parentWorkflowInstanceId

Now that you have the parent workflow instance ID stored in a workflow variable, you can access it from anywhere in your child workflow.

Here is an example of a parent workflow you can import via the designer:

{
  "$id": "1",
  "definitionId": "f3da997090fe4752b4f7abf799f372a8",
  "versionId": "8d6c6e2b441a4d22952a7b19ebf9ceca",
  "name": "Parent",
  "version": 2,
  "variables": {
    "$id": "2",
    "data": {}
  },
  "customAttributes": {
    "$id": "3",
    "data": {}
  },
  "isSingleton": false,
  "persistenceBehavior": "WorkflowBurst",
  "deleteCompletedInstances": false,
  "isPublished": true,
  "isLatest": true,
  "activities": [
    {
      "$id": "4",
      "activityId": "2952daee-646e-431f-b02b-006557507755",
      "type": "RunWorkflow",
      "displayName": "Run Workflow",
      "persistWorkflow": false,
      "loadWorkflowContext": false,
      "saveWorkflowContext": false,
      "properties": [
        {
          "$id": "5",
          "name": "WorkflowDefinitionId",
          "syntax": "Liquid",
          "expressions": {
            "$id": "6",
            "Liquid": "{{ \"Child\" | workflow_definition_id: \"name\" }}"
          }
        },
        {
          "$id": "7",
          "name": "Input",
          "syntax": "JavaScript",
          "expressions": {
            "$id": "8",
            "JavaScript": "({ parentWorkflowInstanceId: workflowInstanceId})"
          }
        },
        {
          "$id": "9",
          "name": "PossibleOutcomes",
          "expressions": {
            "$id": "10"
          }
        },
        {
          "$id": "11",
          "name": "Mode",
          "expressions": {
            "$id": "12"
          }
        },
        {
          "$id": "13",
          "name": "TenantId",
          "expressions": {
            "$id": "14"
          }
        },
        {
          "$id": "15",
          "name": "CorrelationId",
          "expressions": {
            "$id": "16"
          }
        },
        {
          "$id": "17",
          "name": "ContextId",
          "expressions": {
            "$id": "18"
          }
        },
        {
          "$id": "19",
          "name": "CustomAttributes",
          "expressions": {
            "$id": "20"
          }
        }
      ],
      "propertyStorageProviders": {}
    },
    {
      "$id": "21",
      "activityId": "2a6d90ee-5e7a-4d68-8629-386abdaf70ad",
      "type": "HttpEndpoint",
      "displayName": "HTTP Endpoint",
      "persistWorkflow": false,
      "loadWorkflowContext": false,
      "saveWorkflowContext": false,
      "properties": [
        {
          "$id": "22",
          "name": "Path",
          "expressions": {
            "$id": "23",
            "Literal": "/parent"
          }
        },
        {
          "$id": "24",
          "name": "Methods",
          "expressions": {
            "$id": "25",
            "Json": "[\"GET\"]"
          }
        },
        {
          "$id": "26",
          "name": "ReadContent",
          "expressions": {
            "$id": "27"
          }
        },
        {
          "$id": "28",
          "name": "TargetType",
          "expressions": {
            "$id": "29"
          }
        },
        {
          "$id": "30",
          "name": "Schema",
          "syntax": "Literal",
          "expressions": {
            "$id": "31",
            "Literal": ""
          }
        },
        {
          "$id": "32",
          "name": "Authorize",
          "expressions": {
            "$id": "33"
          }
        },
        {
          "$id": "34",
          "name": "Policy",
          "expressions": {
            "$id": "35"
          }
        }
      ],
      "propertyStorageProviders": {}
    }
  ],
  "connections": [
    {
      "$id": "36",
      "sourceActivityId": "2a6d90ee-5e7a-4d68-8629-386abdaf70ad",
      "targetActivityId": "2952daee-646e-431f-b02b-006557507755",
      "outcome": "Done"
    }
  ],
  "id": "8d6c6e2b441a4d22952a7b19ebf9ceca"
}

And here is the Child you can import:

{
  "$id": "1",
  "definitionId": "81efcdb2f9aa473a84931814f5ee1c65",
  "versionId": "cc21182603564d68876efd9079382c27",
  "name": "Child",
  "version": 1,
  "variables": {
    "$id": "2",
    "data": {}
  },
  "customAttributes": {
    "$id": "3",
    "data": {}
  },
  "isSingleton": false,
  "persistenceBehavior": "WorkflowBurst",
  "deleteCompletedInstances": false,
  "isPublished": true,
  "isLatest": true,
  "activities": [
    {
      "$id": "4",
      "activityId": "83c6931f-f481-47c0-add8-3b1ea7d864a2",
      "type": "SetVariable",
      "displayName": "Set ParentWorkflowInstanceId Variable",
      "persistWorkflow": false,
      "loadWorkflowContext": false,
      "saveWorkflowContext": false,
      "properties": [
        {
          "$id": "5",
          "name": "VariableName",
          "expressions": {
            "$id": "6",
            "Literal": "ParentWorkflowInstanceId"
          }
        },
        {
          "$id": "7",
          "name": "Value",
          "syntax": "JavaScript",
          "expressions": {
            "$id": "8",
            "JavaScript": "input.parentWorkflowInstanceId"
          }
        }
      ],
      "propertyStorageProviders": {}
    },
    {
      "$id": "9",
      "activityId": "80e7eb8f-3fca-42a7-be3d-16827bd6ba38",
      "type": "WriteHttpResponse",
      "displayName": "HTTP Response",
      "persistWorkflow": false,
      "loadWorkflowContext": false,
      "saveWorkflowContext": false,
      "properties": [
        {
          "$id": "10",
          "name": "Content",
          "syntax": "Liquid",
          "expressions": {
            "$id": "11",
            "Liquid": "Parent ID: {{ Variables.ParentWorkflowInstanceId }}"
          }
        },
        {
          "$id": "12",
          "name": "ContentType",
          "expressions": {
            "$id": "13"
          }
        },
        {
          "$id": "14",
          "name": "StatusCode",
          "expressions": {
            "$id": "15"
          }
        },
        {
          "$id": "16",
          "name": "CharSet",
          "expressions": {
            "$id": "17"
          }
        },
        {
          "$id": "18",
          "name": "ResponseHeaders",
          "expressions": {
            "$id": "19"
          }
        }
      ],
      "propertyStorageProviders": {}
    }
  ],
  "connections": [
    {
      "$id": "20",
      "sourceActivityId": "83c6931f-f481-47c0-add8-3b1ea7d864a2",
      "targetActivityId": "80e7eb8f-3fca-42a7-be3d-16827bd6ba38",
      "outcome": "Done"
    }
  ],
  "id": "cc21182603564d68876efd9079382c27"
}

Once imported, make sure both workflows are published. You can then invoke the parent workflow via its HTTP endpoint, e.g.: https://localhost:11000/parent

Which will result in a response similar to this:

Parent ID: 0178617bbeca47088e74330c0905237c

This response is generated by the Child workflow (which successfully received the parent workflow instance ID)

Sipke Schoorstra
  • 3,074
  • 1
  • 20
  • 28
  • Thanks for your detailed response. In the meantime I found a similar solution. I passed the `parent` instance Id to `child` worflow via `ContextID` of `child` workflow. Then, as you suggested, the very first step was to “intercept” the contextID and set the `parent` InstanceID as a workflow variable into the `child` wokflow. I followed this aproach since the child workflows already require a dedicated input so I didn’t want to modify the structure of that input. – Octavian Apr 18 '22 at 14:15
  • 1
    From my perspective a more convenient solution would have been to pass any custom value from `parent` to `child` workflow via `Advanced`->`Custom Attributes` of `parent` workflow. I tried to add some values on that field of `parent` worflow but I wasn’t able to get them on `child` worlflow side – don’t know how to access in `elsa designer` a custom attribute – Octavian Apr 18 '22 at 14:15