Workflows
The HumanOS® comes with a built-in workflow engine. It allows to design and run complex workflows along different actors such as humans or computer agents.
Workflows are defined as schema or as classes. Due to rules, a workflow class is dynamically instantiated and started. And of course, also removed dynamically once removal rules are triggered.
In this document, the UML is used to express workflows. There are some extensions to UML necessary to express the full power of HumanOS® Workflows. Following terminology is used:
Name | Short. | Description |
---|---|---|
SceneActivity | Sc | A scene activity contains the whole workflow including exception handling. |
Activity | A | An activity is a set of instructions that can be processed by agents, humans etc. They are embedded in a workflow. |
Actor | Actor | An instance that is able to process an activity |
Control Flow | F~C~ | Flow to the next activity |
Object Flow | F~O~ | Flow of objects, messages etc. (communication between activities). |
The workflow is defined by following attributes:
Attribute | Description | Data Type |
---|---|---|
Id | Id of the workflow. Empty if the schema can be instantiated multiple times. | System.Guid |
Name | Name of the workflow | System.String |
Nodes | Array of activity coordination nodes | |
ControlFlows | Control flow between the activity coordination nodes | |
ObjectFlows | Communication links between ports of an activity and object nodes (space) | |
Arguments | Array of arguments to be passed when starting the workflow. |
Example:
{
"Name": "WorkflowSchema1",
"Id": "8E5BEB09-8BA9-456A-957C-10444A26096D",
"Workflows": [
{
"Name": "Collaboration Workflow",
"Id": "2D962A90-8BD5-44DE-A478-208DE2D49B67",
"Nodes": [],
"ControlFlows": [],
"ObjectFlows": []
}
]
}
Passing Arguments
Arguments can be passed to a workflow. All arguments are stored to the activity context at the start.
- See Commands for notation on arguments.
Example with arguments:
{
"Name": "WorkflowSchema1",
"Id": "8E5BEB09-8BA9-456A-957C-10444A26096D",
"Workflows": [
{
"Name": "Collaboration Workflow",
"Id": "2D962A90-8BD5-44DE-A478-208DE2D49B67",
"Arguments": [
{
"Name": "Value",
"DataType": "System.String",
"Type": "Input"
}
],
"Nodes": [],
"ControlFlows": [],
"ObjectFlows": []
}
]
}
The arguments can then be used inside the workflow, either for guard expressions (see [Guards]) or in C# scripts (see [Scripted Operation]).
Activity Coordination Node
There exist different node types to coordinate the workflow:
Type | Description |
---|---|
InitialNode | Used to start a workflow (entry point). |
DecisionNode | Node to branch the control flow according to some conditions. |
MergeNode | Node to combine two control flows to one. |
ForkNode | Node to fork the control flow into two concurrently running flows (multithreading) |
JoinNode | Node to join concurrently running control flows back to one. The flow will continue after all incoming flows are triggered. |
GenericActivity | An activity node. |
ActivityFinalNode | Node to terminate the workflow. |
FlowFinalNode | Node to stop a control flow. This will not terminate the workflow, just consume a control flow. |
ExceptionHandler | Special node to catch exception within a workflow and to continue an alternative control flow. |
ObjectNode | Object space to exchange information between activities. |
Each node is declared as a "MemberInfo".
Attribute | Description | Data Type |
---|---|---|
Name | Name of the node | System.String |
Type | Type of node, e. g. InitialNode | System.String |
Example:
{
"Name": "Start",
"Type": "InitialNode"
}
Control Flows
The control flow is a relational link between nodes.
Attribute | Description | Data Type |
---|---|---|
Name | Name of the flow. | System.String |
Node1RefName | Reference name of the source node | System.String |
Node2RefName | Reference name of the target node | System.String |
GuardCondition | Guard used from outgoing control flows from DecisionNodes | System.String |
Guards
After decision nodes, the guards of a control flow are checked to decide which flow to take. For all other coordination nodes, guards are ignored:
Example:
Example:
{
"Name": "Collaboration Workflow",
"Id": "2D962A90-8BD5-44DE-A478-208DE2D49B67",
"Nodes": [
{
"Name": "Start",
"Type": "InitialNode"
},
{
"Name": "Activity1",
"Type": "GenericActivity"
},
{
"Name": "End",
"Type": "ActivityFinalNode"
}
],
"ControlFlows": [
{
"Node1RefName": "Start",
"Node2RefName": "Activity1"
},
{
"Node1RefName": "Activity1",
"Node2RefName": "End"
}
]
}
Activity Nodes
An activity node describes a set of operations, a work or procedure to be performed by an agent (see Agents and Skills).
Other than UML, there exists no such construct like "swimming-planes". HumanOS™ selects agents according to their skills and the skills needed to perform an activity.
An activity is described by following attributes:
Attribute | Description | Data Type |
---|---|---|
Id | Id of the activity. Empty if the schema can be instantiated multiple times. | System.Guid |
Name | Name of the activity | System.String |
Type | Type of activity, = GenericActivity | System.Type |
ActorSkill | Skills needed to perform the activity (see [Agents and Skills]) | System.Guid |
AutoReset | Flag, to reset the activity after its completion. This is needed, if the activity can be executed multiple times. | System.Boolean |
Description | Some description | System.String |
Operations | Array of operations to be executed |
Example:
{
"Id": "6FA7E8CB-D2D1-4C22-9122-A7DAFFD2B5C7",
"Name": "Activity_ManageDeviceReferences",
"Type": "GenericActivity",
"AutoReset": true,
"ActorSkill": "54C4FA92-F385-4644-B929-5650310B4930",
"Operations": []
}
Operations
Each activity can have a list of operations.
Attribute | Description | Data Type |
---|---|---|
Name | Name of the operation. | System.String |
Type | Type of operation
| System.Type |
Instruction | Instruction to be executed (only for Human- and CSharpScriptOperation) | System.String |
CommandInstruction | Instruction for CommandedOperation | |
Condition | [OPT] Condition expression. Default is true. | System.String |
Scripted Operation
The workflow script class must be derived from the TAbstractOperationScriptObject. The method run()
implements the operation to be performed.
Following objects are passed to the script as arguments:
IKernelAccess Kernel
: access interface to the kernelIActivity Activity
: access to the activity object and the calling context
The script files are located in $(ConfigPath)\Scripts\Workflows
.
Example:
public class TWorkflow_MyOperation : TAbstractOperationScriptObject
{
///<see cref="TAbstractOperationScriptObject"/>
public override void run(IKernelAccess Kernel, IActivity Activity)
{
string strHostName = Activity.Context.getValue<string>("HostName");
TLogger.writeInfo(strHostName + ": BasicConfiguration started...");
IGroupRelation Device = Activity.Context.getValue<IGroupRelation>("Device");
Dictionary<string, object> dicInput = new Dictionary<string, object>();
dicInput["ObjectId"] = Activity.Context.getValue<string>("ObjectId");
dicInput["Action"] = "A0"; //no action
dicInput["Status"] = "S3"; //next step is user configuration
Dictionary<string, object> dicOutput = new Dictionary<string, object>();
TCommandResult Result = TCommandHelper.call(Kernel,
Guid.Parse(GUID_iDoit_LogicSetDeviceStatusAndAction), dicInput, dicOutput);
if (Result.State != EProcessingState.Good)
{
throw new ArgumentException(strHostName +
": Could not set the device status and action.", Result.ErrorInfo);
}
TLogger.writeInfo(strHostName + ": BasicConfiguration finished. Reboot required.");
}
}
- More information about operation scripting, see "HumanOS® Kernel SDK Manual".
Exception Handling in Workflows
If an exception is thrown during processing, the complete workflow stops with error. There is an extension allowing to handle the exceptions explicitly in a separate control flow of the workflow.
- A Workflow can also contain several exception handlers. Make sure, each handler declares another exception class type.
- To handle all exceptions with one exception handler, declare ExceptionTypeName as
System.Exception
.
Example:
{
"Id": "B65C2AD1-78E8-479A-80D2-84FC86D32AA9",
"Name": "MyWorkflow",
"Nodes": [
{
"Id": "7E4BD883-92AE-4DBF-AC32-0D380BB9F216",
"Name": "Start",
"Type": "InitialNode"
},
{
"Id": "6FA7E8CB-D2D1-4C22-9122-A7DAFFD2B5C7",
"Name": "Activity1 ",
"Type": "GenericActivity",
"AutoReset": true,
"ActorSkill": "54C4FA92-F385-4644-B929-5650310B4930",
"Operations": [
{
"Name": "Operation1",
"Type": "CSharpScriptOperation",
"Instruction": "MyScript.cs"
}
]
},
{
"Id": "ADD55B7C-59F1-4CF7-9257-509B19E70C6F",
"Name": "ExceptionHandler",
"Type": "ExceptionHandler",
"Properties": [
{
"Name": "ExceptionTypeName",
"Value": "System.Exception"
}
]
},
{
"Id": "6B43DBD5-92FA-4304-8BDA-A2AB5793644A",
"Name": "TerminateActivity",
"Type": "GenericActivity",
"AutoReset": true,
"ActorSkill": "54C4FA92-F385-4644-B929-5650310B4930",
"Operations": [
{
"Name": "Operation1",
"Type": "CSharpScriptOperation",
"Instruction": "TTerminateHumanOS.cs"
}
]
},
{
"Id": "111C3571-62A1-4BC5-84FE-1D872953C1BE",
"Name": "End",
"Type": "ActivityFinalNode"
}
],
"ControlFlows": [
{
"Name": "Flow_Start_Activity1",
"Node1RefName": "Start",
"Node2RefName": " Activity1"
},
{
"Name": "Flow_Activity1_End",
"Node1RefName": "Activity1",
"Node2RefName": "End"
},
{
"Name": "Flow_ExceptionHandler_TerminateActivity",
"Node1RefName": "ExceptionHandler",
"Node2RefName": "TerminateActivity"
},
{
"Name": "Flow_TerminateActivity_End",
"Node1RefName": "TerminateActivity",
"Node2RefName": "End"
}
]
}
Critical Workflow Termination
To implement system relevant or critical workflows, the script of the error-handler-activity should pass the exception to the kernel object. This will immediately terminate the HumanOS process with that error.
using HumanOS.Kernel.DataModel;
using HumanOS.Kernel.Workflow.Activity;
using HumanOS.Kernel.Workflow.Instruction;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HumanOS.Kernel.Test.TestFiles.Scripts.Workflows
{
/// <summary>
/// Handles the critical exceptions
/// </summary>
public class THandleExceptions : TAbstractOperationScriptObject
{
///<see cref="TAbstractOperationScriptObject"/>
public override void run(IKernelAccess Kernel, IActivity Activity)
{
Kernel.postFatalError(Activity.Context.ErrorInfo);
}
}
}