danielgerlag / workflow-core

Lightweight workflow engine for .NET Standard
MIT License
5.33k stars 1.19k forks source link

How to rollback service Transaction #1258

Open MOwaisfarooq opened 5 months ago

MOwaisfarooq commented 5 months ago

If an error occurs in step B of the workflow, I suspend the workflow to publish this event later from the controller API. The _workflowStepDetailsService.UpdateTransactionForStepB has made a transaction in my table stepTable. I want to revert only the step B service transaction that updated the table. I don't want to undo everything, so that next time I can continue from step B after the error. For example, if I made an insertion in step A using _workflowStepDetailsService.CreateTransactionforStepA in my stepTable, I want to preserve that transaction and only undo the changes made by step B. builder .StartWith(context => Console.WriteLine("Begin")) .UseDefaultErrorBehavior(WorkflowErrorHandling.Suspend) .Saga(saga => saga .StartWith<stepA>() .Then<stepB>() .Then<stepC>() ) .CompensateWith<**UndoEverything**>() .Then(context => Console.WriteLine("End")); `` public class stepA: StepBodyAsync {

private readonly IWorkflowStepDetailsService _workflowStepDetailsService;

public stepA(IWorkflowStepDetailsService workflowStepDetailsService)
{
    _workflowStepDetailsService = workflowStepDetailsService;
}

public override async Task<ExecutionResult> RunAsync(IStepExecutionContext context)
{

    if (!context.ExecutionPointer.EventPublished)
    {
        return ExecutionResult.WaitForEvent("StartWorkflowEvent", context.Workflow.Id, DateTime.Now);
    }

    var workflowsteprequest = (WorkFlowStepDetails)context.ExecutionPointer.EventData;
    await _workflowStepDetailsService.CreateTransactionforStepA(workflowsteprequest);

    return ExecutionResult.Next();
}

}

public class stepB : StepBodyAsync { private readonly IWorkflowStepDetailsService _workflowStepDetailsService;

public stepB: (IWorkflowStepDetailsService workflowStepDetailsService)
{
    _workflowStepDetailsService = workflowStepDetailsService;
}

public override async Task<ExecutionResult> RunAsync(IStepExecutionContext context)
{

    if (!context.ExecutionPointer.EventPublished)
    {
        return ExecutionResult.WaitForEvent("StartWorkflowEvent", context.Workflow.Id, DateTime.Now);
    }

    var workflowsteprequest = (WorkFlowStepDetails)context.ExecutionPointer.EventData;

    await _workflowStepDetailsService.UpdateTransactionForStepB(workflowsteprequest);

    return ExecutionResult.Next();
}

}