Table of Contents

Acuit Pinpoint Workflows

Acuit Pinpoint workflows allow various kinds of processes to be defined via workflow definition files. This allows various processes within Acuit Pinpoint to be customized without the need to write custom code.

Acuit Pinpoint currently allows workflows to be leveraged in the following ways:

  • To define custom processes that should occur in response to various events raised within Acuit Pinpoint Workstation. See Workflow Events for more information.
  • To define test processes for test types within Acuit Pinpoint Workstation. See Test Workflows for more information.
  • As a framework for custom code within Acuit Pinpoint plug-ins to manage various kinds of configurable workflows. Plug-ins can simply reference the applicable NuGet packages and use the workflow APIs as desired.

The following concepts should be understood when working with Acuit Pinpoint workflows.

Workflows

A "workflow" refers to a single defined process. A workflow is a structured composition of activities, similar to a flowchart. (Technically, a workflow is really just a single root activity that contains all other activities making up the workflow. Often, this root activity will be a Sequence, but it can be any activity type.)

The workflow is the process definition. To actually use the workflow, it must be executed. Each execution of a workflow is independent. A workflow can be executed multiple times, even simultaneously. Once execution of a workflow has been started, it will run to completion. Activities can fail or be canceled, which will affect how the workflow completes, depending on how it is defined, but the workflow will still run to "completion," one way or another.

When using workflows via standard Acuit Pinpoint features, Acuit Pinpoint handles the details of executing workflows for you. When using workflows within your own custom code, workflows can be executed in one of two ways:

  • Directly invoked via WorkflowInvoker.
  • Hosted within a WorkflowHost. The workflow host allows for greater outside integration with the running workflow.
Note

Technical note for when writing code using Acuit Pinpoint workflows:

Workflows are fully asynchronous, which ensures desktop applications like Acuit Pinpoint Workstation remain responsive to the user while a workflow executes. However, workflows are not thread-safe. This means:

  • Custom activities should capture and use the synchronization context in their code (i.e., they should not use ConfigureAwait(false)).
  • If workflows are being used outside of a desktop application, a synchronization context must be provided that ensures workflow-related code cannot execute simultaneously in different threads.
  • Note that custom activity implementations can be multi-threaded (e.g., to communicate with external devices), as long as any interaction with the workflow framework itself does not happen from a background thread.

Workflows are assumed to be relatively short-lived; there is no facility for saving and restoring workflow execution state. For example, if a workflow is running within Acuit Pinpoint Workstation, the application cannot be closed and restarted with the workflow resuming where it left off. Closing Acuit Pinpoint Workstation would cause the running workflow to be canceled as part of the application shutdown process.

Activities

Activities are individual steps of a workflow. Every activity type derives from Activity. A standard set of activities is included with Acuit Pinpoint, but custom activities can be created as well. Some activities might perform specific actions, like turning on power to the unit under test. Some activities might perform logic. Activities can contain and execute child activities as well, such as Sequence, which simply executes a list of child activities in sequence.

Each activity in a workflow is defined by specifying the activity type, along with:

  • Optionally, a list of parameters applicable to the activity and any children.
  • Optionally, a list of variables applicable to the activity and any children.
  • Values for zero or more properties that define the operation of the activity.

The properties vary depending on the specific activity. Some properties are required while others are optional. It is possible for a property to require a fixed literal value, but most activity properties accept expressions. When an activity starts to execute, it will evaluate and validate its property values. If any required values are missing or any provided values are invalid, the activity execution will fail. Sometimes activity properties are evaluated multiple times while the activity is running.

See the Acuit.Pinpoint.Workflows.Activities namespace for the list of standard activities.

Parameters

Parameters are input data values that a workflow (or a specific activity or set of activities within a workflow) requires. Any activity can define the parameters that it requires, specifying for each parameter:

  • A parameter name.
  • The parameter data type.
  • The default value for the parameter.
  • A parameter description.

Typically, the workflow's root activity will define all parameters used by the workflow. Child activities inherit all parameters defined by ascendant activities, but they can also define additional parameters, which can be useful when one activity makes new parameters available to its child activities.

Tip

Even though parameters are defined for a particular activity, think of them as required input parameters for the workflow (or a portion thereof). They are in the domain of the workflow (e.g,. "burn-off time" within a run test workflow) but are used within the workflow by specific activities, often as activity property values (e.g., as the Duration value for a Delay) activity.

Parameters must have values. When an activity is executed, if any of its parameters do not have a value, the activity will fail. The workflow defines the list of parameters, providing default values when appropriate, but typically some parameter values come from outside of the workflow definition. For example, certain run test parameters may depend on the model of the unit being tested and come from a run test parameters table maintained outside of the workflow.

Parameters provided to an executing activity will never change while the activity is executing. However, since the parameter values for an activity are evaluated as the activity execution is starting, it is possible for the value for a particular parameter to be different for an activity that executes multiple times during a workflow (e.g., if the parameter value is coming from a settings.json file that is being updated).

"Parameter value providers" are used to provide parameter values to executing workflows. When using workflows via standard Acuit Pinpoint features, Acuit Pinpoint will provide built-in parameter value providers for your workflows such as key/value configuration settings or Acuit Pinpoint tables. In code, a parameter value provider is any class that implements IParameterValueProvider.

Variables

Tracking data and exchanging data across activities within a workflow are accomplished using variables. Variables are similar to parameters in that they are named, they must be defined within a workflow for a particular activity (optionally, with a default value), and they are available to any child activities as well. Unlike parameters, activities can change their value at any time. For example, the SetVariable simply sets a variable value, while the Stopwatch activity can update a variable with its elapsed time.

The variables defined on the root activity for a workflow also serve as the workflow's data context.

Data Context

The workflow data context provides a way for the workflow to make data available to the outside world. The data context is simply the collection of variables defined for the root activity in the workflow.

Event Bus

Another way to communicate between activities or from outside the workflow is via the event bus. Each running workflow has an event bus that all executing activities share, watching for events to be raised of particular types.

Custom activities can define and use their own event types, but Acuit Pinpoint Workstation provides one standard event type: UICommandEvent. The WaitForUICommand activity can be used in a workflow to watch for this event. (How this event gets raised depends on the environment hosting the workflow).

Expressions

Most activity properties accept expressions for their values via XML attributes in XAML. Expressions are strings that contain code that can be evaluated to produce a value of the acivity property type.

The workflow XAML parser interprets XML attribute strings for these properties like this:

  1. If the string value is surrounded by square brackets ([ and ]), then the text within the square brackets is interpreted as an expression. For example:
    <SetVariable Name="Result" Value="[2 + 3]" />
    
  2. Otherwise, the string value is interpreted as a literal value and is attempted to be converted to the property type. For example:
    <SetVariable Name="Result" Value="5" />
    
    To specify a literal value that starts with [ and ends with ], prefix it with %. For example, for a literal string value of "[literal]":
    <SetVariable Name="Result" Value="%[literal]" />
    

Expressions are defined using C# syntax, with the following environment:

  • These assemblies are referenced:

    • Core .NET assemblies
    • Acuit.Pinpoint.Workflows
    • Acuit.Pinpoint.Workstation.Interfaces
    • Microsoft.CSharp
  • These namespaces are imported:

    • System
    • System.Linq
  • These global properties are available:

    Acuit.Pinpoint.Workflows.Parameters.IParametersStorage Parameters { get; }
    Acuit.Pinpoint.Workflows.IVariablesStorage Variables { get; }
    dynamic param { get; }
    dynamic var { get; }
    

    Expressions should normally use param to access parameters dynamically (e.g., param.ParamName or param.ParamGroup.ParamName), and var to access variables dynamically (e.g., var.VariableName).

As an example, the Delay activity has a Duration property that must be specified that requires a TimeSpan value. Some ways this could be configured in XAML include:

Example Activity Definition (XAML) Description
A literal value. <Delay Duration="0:00:05" /> Delays for five seconds.
From a parameter. <Delay Duration="[param.Delay1]" /> Delays for the time specified by the Delay1 parameter, which must be defined and available to this activity, and must be of type TimeSpan.
From a variable. <Delay Duration="[var.DelayCalc]" /> Delays for the time specified by the current value of the DelayCalc variable, which must be defined and available to this activity, and must be of type TimeSpan.
From a C# expression <Delay Duration="[param.Delay1 + var.DelayCalc]" /> Delays for the time specified by the Delay1 parameter plus the time specified by the current value of the DelayCalc variable, both of which must be defined and available to this activity, and must be of type TimeSpan.

Note that when the global param and var properties are used to access parameters or variables, the expression compiler will treat the values returned as dynamic, which has the following implications:

  • To use extension methods, against a variable or parameter, be sure to cast the value to its type first. For example, to use the Linq Any extension method on a parameter of type int[]:\
    <Sequence xmlns="http://schemas.acuit.com/pinpoint/2020/xaml/workflows">
        <Sequence.Parameters>
            <Parameter Name="Readings" Type="int[]" />
        </Sequence.Parameters>
        <If Condition="[((int[])param.Readings).Any(r => r > 100)]">
            ...
        </If>
    </Sequence>
    

Services

Workflow activities sometimes need to use services to execute. For example, an activity that turns power on to the unit being testing needs access to a tester service that knows how to do that. When a workflow is executed, it is given a service provider that can provide these services as needed.

When subsequent child activities are executed, they can be given a service provider that augments the original service provider with new services that are specific to that activity. This is the primary mechanism used to provide context to certain activities, such as a SetTestDataItem activity that records test data for a unit test that is being managed by an ascendant RecordTest activity).

Activities should document what services they require, and the workflow host or workflow invoker must ensure the activities used by the workflow are required. For example, the Delay activity requires the ITimeService service.

When using workflows via standard Acuit Pinpoint features, Acuit Pinpoint will ensure that all basic services are available.