Back to Workflow Core

Workflow Core 1.6.0

ReleaseNotes/1.6.0.md

3.17.03.2 KB
Original Source

Workflow Core 1.6.0

  • Added Saga transaction feature
  • Added .CompensateWith feature

Specifying compensation steps for each component of a saga transaction

In this sample, if Task2 throws an exception, then UndoTask2 and UndoTask1 will be triggered.

c#
builder
    .StartWith<SayHello>()
        .CompensateWith<UndoHello>()
    .Saga(saga => saga
        .StartWith<DoTask1>()
            .CompensateWith<UndoTask1>()
        .Then<DoTask2>()
            .CompensateWith<UndoTask2>()
        .Then<DoTask3>()
            .CompensateWith<UndoTask3>()
    )
    .Then<SayGoodbye>();

Retrying a failed transaction

This particular example will retry the entire saga every 5 seconds

c#
builder
    .StartWith<SayHello>()
        .CompensateWith<UndoHello>()
    .Saga(saga => saga
        .StartWith<DoTask1>()
	    .CompensateWith<UndoTask1>()
	.Then<DoTask2>()
	    .CompensateWith<UndoTask2>()
	.Then<DoTask3>()
	    .CompensateWith<UndoTask3>()
	)		
	.OnError(Models.WorkflowErrorHandling.Retry, TimeSpan.FromSeconds(5))
	.Then<SayGoodbye>();

Compensating the entire transaction

You could also only specify a master compensation step, as follows

c#
builder
	.StartWith<SayHello>()
		.CompensateWith<UndoHello>()
	.Saga(saga => saga
		.StartWith<DoTask1>()
		.Then<DoTask2>()
		.Then<DoTask3>()
	)		
        .CompensateWithSequence(comp => comp
            .StartWith<UndoTask1>()
            .Then<UndoTask2>()
	    .Then<UndoTask3>()
        )
	.Then<SayGoodbye>();

Passing parameters

Parameters can be passed to a compensation step as follows

c#
builder
    .StartWith<SayHello>()
    .CompensateWith<PrintMessage>(compensate => 
    {
        compensate.Input(step => step.Message, data => "undoing...");
    })

Expressing a saga in JSON

A saga transaction can be expressed in JSON, by using the WorkflowCore.Primitives.Sequence step and setting the Saga parameter to true.

The compensation steps can be defined by specifying the CompensateWith parameter.

json
{
  "Id": "Saga-Sample",
  "Version": 1,
  "DataType": "MyApp.MyDataClass, MyApp",
  "Steps": [
    {
      "Id": "Hello",
      "StepType": "MyApp.HelloWorld, MyApp",
      "NextStepId": "MySaga"
    },    
    {
      "Id": "MySaga",
      "StepType": "WorkflowCore.Primitives.Sequence, WorkflowCore",
      "NextStepId": "Bye",
      "Saga": true,
      "Do": [
        [
          {
            "Id": "do1",
            "StepType": "MyApp.Task1, MyApp",
            "NextStepId": "do2",
            "CompensateWith": [
              {
                "Id": "undo1",
                "StepType": "MyApp.UndoTask1, MyApp"
              }
            ]
          },
          {
            "Id": "do2",
            "StepType": "MyApp.Task2, MyApp",
            "CompensateWith": [
              {
                "Id": "undo2-1",
                "NextStepId": "undo2-2",
                "StepType": "MyApp.UndoTask2, MyApp"
              },
              {
                "Id": "undo2-2",
                "StepType": "MyApp.DoSomethingElse, MyApp"
              }
            ]
          }
        ]
      ]
    },    
    {
      "Id": "Bye",
      "StepType": "MyApp.GoodbyeWorld, MyApp"
    }
  ]
}