将多个顺序功能作为一个工作单元执行并支持回滚的设计模式
Design pattern to execute multiple sequential functions as a unit of work and support rollbacks
我有一个复杂的审核申请提交流程,需要执行几个步骤。
ReviewService.CreateReview()
- CheckReservedTimeslotIsAvailable
- 处理付款
- 创建会议
- 插入评论
- 更新财务日志
- 完成文档
- 通知
所有这些步骤都编码在 CreateReview() 方法中,并且变得 un-readable,难以管理。此外,当前的实现不支持回滚。
所以我的想法是创建一个 Orchestrator class 并构建步骤序列。如果所有步骤都已完成,协调器会确保创建成功的审核。如果任何步骤未能完成,则所有已完成的前面功能都将回滚以确保数据完整性。
这与 Saga 模式(编排)几乎相同,但略有变化,步骤不是微服务。
这是正确的模式吗?或者命令模式是一个不错的选择?请指教
BaseOrchestrator
...
使用系统;
使用 System.Collections.Generic;
/// <summary>
/// Facilitates runnning of the pipeline operations.
/// </summary>
/// <typeparam name="T">The type of object orchestrator is executed on.</typeparam>
public abstract class BaseOrchestrator<T> : IOrchestrator<T>
{
protected T data;
protected List<Action> Steps;
protected int rejectReason;
public BaseOrchestrator<T> Begin(Action stepToExecute)
{
RegisterStepToExecute(stepToExecute);
return this;
}
public BaseOrchestrator<T> Step(Action stepToExecute)
{
RegisterStepToExecute(stepToExecute);
return this;
}
public BaseOrchestrator<T> End(Action stepToExecute)
{
RegisterStepToExecute(stepToExecute);
return this;
}
public BaseOrchestrator<T> WithRollback(Action stepToExecute)
{
RegisterStepToExecute(stepToExecute);
return this;
}
protected BaseOrchestrator<T> RegisterStepToExecute(Action stepToExecute)
{
Steps.Add(stepToExecute);
return this;
}
public BaseOrchestrator<T> StepBuilder()
{
Steps = new List<Action>();
return this;
}
/// <inheritdoc/>
public void Execute(T data)
{
...
}
}
...
命令模式在这种情况下更好,因为您是在构建查询的同时进行的。您不必处理多个数据库中的数据,因此不必处理 2PC。然而,如果您使用 Saga,您将在每种方法上提交事务,这对您并没有多大好处,并且可能会在长 运行.
中增加更多的复杂性
假设出现暂时性网络问题并且一个方法失败并且回滚在前两个回滚上有效,但在下一个回滚时失败?
我有一个复杂的审核申请提交流程,需要执行几个步骤。
ReviewService.CreateReview()
- CheckReservedTimeslotIsAvailable
- 处理付款
- 创建会议
- 插入评论
- 更新财务日志
- 完成文档
- 通知
所有这些步骤都编码在 CreateReview() 方法中,并且变得 un-readable,难以管理。此外,当前的实现不支持回滚。
所以我的想法是创建一个 Orchestrator class 并构建步骤序列。如果所有步骤都已完成,协调器会确保创建成功的审核。如果任何步骤未能完成,则所有已完成的前面功能都将回滚以确保数据完整性。 这与 Saga 模式(编排)几乎相同,但略有变化,步骤不是微服务。
这是正确的模式吗?或者命令模式是一个不错的选择?请指教
BaseOrchestrator ... 使用系统; 使用 System.Collections.Generic;
/// <summary>
/// Facilitates runnning of the pipeline operations.
/// </summary>
/// <typeparam name="T">The type of object orchestrator is executed on.</typeparam>
public abstract class BaseOrchestrator<T> : IOrchestrator<T>
{
protected T data;
protected List<Action> Steps;
protected int rejectReason;
public BaseOrchestrator<T> Begin(Action stepToExecute)
{
RegisterStepToExecute(stepToExecute);
return this;
}
public BaseOrchestrator<T> Step(Action stepToExecute)
{
RegisterStepToExecute(stepToExecute);
return this;
}
public BaseOrchestrator<T> End(Action stepToExecute)
{
RegisterStepToExecute(stepToExecute);
return this;
}
public BaseOrchestrator<T> WithRollback(Action stepToExecute)
{
RegisterStepToExecute(stepToExecute);
return this;
}
protected BaseOrchestrator<T> RegisterStepToExecute(Action stepToExecute)
{
Steps.Add(stepToExecute);
return this;
}
public BaseOrchestrator<T> StepBuilder()
{
Steps = new List<Action>();
return this;
}
/// <inheritdoc/>
public void Execute(T data)
{
...
}
}
...
命令模式在这种情况下更好,因为您是在构建查询的同时进行的。您不必处理多个数据库中的数据,因此不必处理 2PC。然而,如果您使用 Saga,您将在每种方法上提交事务,这对您并没有多大好处,并且可能会在长 运行.
中增加更多的复杂性假设出现暂时性网络问题并且一个方法失败并且回滚在前两个回滚上有效,但在下一个回滚时失败?