Workflows.NET

A simple library for executing sequential workfows. Supports dependencies management, rollback and failure handling.

Workflows.NET @ NuGet
Workflows.NET.StepAdapter @ NuGet
Sources on GitHub

Quick start

It is very easy to get started. You should define a class that will represent an execution context. Then define classes that will represent workflow steps, accepting this context. Next you need to create an instance of the Workflow, configure it with the step classes and execute it, providing an instance of context. Then you can use context to get results of workflow execution.

Success and Crash handling

Whenever during execution all steps of the workflow either succeeded or skipped, workflow will execute success handler. If any of the steps during execution throw an unexpected exception, that is not handled by the step itself by calling Failed() method, workflow will call a crash handler, and pass it failed step, context and exception. Use crash handler to perform logging, cause there is something really bad happened to this step.

Important
Please, note, that whenever any of the step crashes, execution of the workflow will be terminated.

Order of execution

By default you are not guaranteed that steps will be executed in order you added them to workflow. To ensure, that a certain step will be executed only when execution context is in the right state you can use one or more Requires attributes to specify which steps should be executed prior to the step decorated with this attribute.

Internally workflow will discover all the dependencies between steps, and apply topological sort, to execute steps in correct order. For example:

topological sort example

If step A depends on B, and C to be executed first, and step C depends on B, then order of execution will be B then C then A

Execution flow

A Step base class defines two methods for controlling execution flow. These are: Fail() and Skip(). Whenever you call any of this methods in your step class, the execution of the step will be terminated.

The difference between those two is that Fail() will mark current step as failed, all the dependent steps will be marked as failed, and workflow will not trigger success handler. When you call Skip(), step will be marked as skipped, all the dependent steps will be marked as skipped, but workflow may still succeed and call success handler after execution.

Even if any of the steps will fail by calling Fail() method, other steps, that do not depend on failed steps, will still be attempted to execute. This way, workflow ensures, all the potential errors will be detected at a single execution.

If either Skip() or Fail() methods will be called inside step, all steps, that depend on it will not be executed.

Important
Both Skip() and Fail() internally throw an exception, which means execution of the current step, will be terminated after calling any of those methods.

Rollback after failure

At the moment workflow fails to execute, or crashes, all steps successfully execued so far will be given a chance to rollback their execution results, if any. To perform a rollback a step should override Rollback method of Step base class.

In the following example, if ReadFileStep will fail, the whole workflow will fail. Therefore, workflow will call CreateTempFileStep.Rollback() method, so it can cleanup temp file.

Dependency Injection support

By default workflow creates instances of step classes using default parameter-less constructor. However it is possible to use your favorite DI container to create workflow steps.

To do this, you can implement and provide your own IStepActivator interface implementation.

Adapted steps

The Workflows.NET.StepAdapter library is an extension to Workflows.NET that allows to add steps to workflow, that do not inherit base Step class. This is done to improve testability of code based on Workflows.NET library, as well as loosen coupling of your projects to Workflows.NET library. It is done by wrapping your class in a StepAdapter class.

Still, your class needs to follow some conventions, in order to interact with Workflow, and be executable by Workflow. Those will be explained below.

Bare minimum

At minimum your class needs to declare Execute method, that returns void and accepts single parameter of you'r context type.

Important Before using adapted steps, you should register step factory in WorkflowServices. See example below, in the HomeController constuctor. In a real-life application, however, this should be done only once during application start, before using Workflows.

Fail and Skip

In order to interact with workflow, instead of Fail and Skip methods, defined in Step<T> class, your class should declare two events Failed and Skipped accordingly. It will be a good idea to move those events to the common base class of your own, and inherit your steps from it.

Workflow adds handlers to Failed and Skipped events, that throw exceptions. Whenever you invoke Failed or Skipped event handlers, execution of the step will be terminated. Just like it is done in Step<T> base class

Backward compatibility

Even when using this extension, you can still use steps based on Step<T> class, you can even mix both types of steps in a single workflow.

Please note
All the dependency management is still applied to adapted steps. See Workflows.NET execution flow example.