补偿(Compensation)
基本概念
首先我们来回顾下事务的加锁机制。事务在提交之前会加锁记录以防止来自其它执行过程的查询.但是长期加锁事务不仅磨灭程序的可伸缩性,甚至会造成死锁。
所谓补偿,简单的说就是时空隧道,对之前做过的正确的事情重新做一遍。它抛开锁机制去尽可能快的提交事务并继续执行.如果之后某一点发生了错误,我们再去弥补之前完成的事务,也许这样做并不能逆转事务,但我们可以采取其它的措施(譬如取消)来弥补这个事务失败所造成的影响。
在WF3.5中,我们只能补偿实现了ICompensatableActivity接口的活动.在基本活动库中,CompensatableSequenceActivity和CompensatableTransactionScopeActivity都实现了这个接口.。(待核实)
CompensatableSequenc活动的功能相当于附加了补偿处理程序(Compensation Handler)的Sequence活动.我们可以通过右键菜单的View Compensation Handler来查看补偿处理器视图
在补偿处理程序视图中,我们可以添加活动来对其子活动进行补偿。
CompensatableTransactionScope活动的功能相当于附加了补偿处理程序的TransacionScope,所以CompensatableTransactionScope活动也不能包含CompensatableTransactionScope活动作为其子活动.
在CompensatableTransactionScope活动的补偿处理程序视图中,我们可以使用活动来定义补偿的逻辑.
记住,补偿只当被补偿活动顺利完成时才会生效.
我们只能补偿实现了ICompensatableActivity接口的活动.除了刚才提到的这两个基本活动库中的活动之外,我们还可以创建实现ICompensatableActivity接口的自定义活动.
为Compensate活动的TargetActivityName属性指定需要补偿的活动,Runtime就会执行目标活动的补偿处理程序.Compensate活动只能存在于错误处理程序或补偿处理程序中.当此活动在补偿处理程序中时,它还可以引发其子活动事务的补偿. 或许这里让人有些难以理解,我再解释一下:
可以把Compensate活动视作一个触发器,它可以触发目标活动的补偿处理程序,使其进行补偿.
使用Compensate进行补偿的目标活动必须实现ICompensatableActivity接口,而且一定要顺利完成,因为我们之前提到,所谓补偿就是一个”亡羊补牢”的过程,错误的产生和发现应该是在事务提交之后,此时Compensate活动需要置于错误处理程序中.
如果某个可补偿的活动内部还包含了可补偿的子活动(比如嵌套的CompensatableSequence活动),而且其子活动在提交事务之后的某一步发生了错误,那么在这个活动(而不是它的子活动)的补偿处理程序中添加Compensate活动可以对此错误进行补偿.
定义补偿
简述
Compensate活动用来补偿之前完成的并且需要补偿的活动。因此
CompenationHandler当工作流有异常或活动执行取消完成后方执行;
ConfirmationHandler为工作流正常执行完成后方执行;
CancellationHandler为活动取消时方执行。
Result:活动执行结果的参数。
代码方式实例:
new CompensableActivity
{
Body = new WriteLine { Text = " CompensableActivity: Do First Action" },
ConfirmationHandler = new WriteLine { Text = " CompensableActivity: Confirm First Action" },
CompensationHandler = new WriteLine { Text = " CompensableActivity: Compensate First Action" },
CancellationHandler = new WriteLine { Text = " CompensableActivity: Cancel First Action" },
Result = tokenA
},
声明方式实例:
因为使用xaml进行定义,xml属于声明式编程(Declarative program)的一种。
显式调用补偿活动
使用Confirm来显式调用CompensationHandler活动,使用Compensate显式调用ConfirmationHandler活动。
使用CompensationToken
CompensationToken,用来通过记录发放令牌来安排补偿活动的执行顺序。
关于CompensableActivity容器中活动的执行顺序
1、 当流程完成时会自动调用CompensableActivity容器自动执行所有[CompensableActivity]中的ConfirmationHandler;
2、 只有为 [实例.OnUnhandledException]指定[ UnhandledExceptionAction.Cancel]时,当流程在[CompensableActivity]的外部产生异常,才会自动调用[CompensableActivity]中的CompensationHandler;
3、 只有为 [实例.OnUnhandledException]指定[ UnhandledExceptionAction.Cancel]时
4、 当流程在[CompensableActivity]的[Body]部分产生异常,才会自动调用[CompensableActivity]中的CompensationHandler
CancellationHandler与 CompensationHandler的区别
当异常发生在[CompensableActivity]外部时,会调用 [CompensationHandler]
当异常发生在[CompensableActivity.Body]部分时,会调用 [CancellationHandler] [CompensationHandler]可以被[Compensate] 显示调用
5、 显示调用的时候,活动的执行顺序
显式调用CompensableActivity
使用[Confirm]可以显示调用[CompensableActivity]的[ConfirmationHandler]部分
使用[Compensate]可以显示调用[CompensableActivity]的[CompensationHandler]部分
要显示调用[CompensableActivity],需要定义一个[ System.Activities.Statements.CompensationToken]型变量,将[CompensableActivity]的[Result]绑定到该变量上.再将[Confirm]或[Compensate]的[Target]属性绑定到该变量上即可实现显示调用
一个[CompensableActivity]只能被调用一次.调用两次以上会出错
如果[Confirm]调用后,[Compensate]再调用会出错
如果[Compensate]调用后,[Confirm]再调用会出错
[Confirm]或[Compensate]调用后,不会再被自动调用
显式调用Confirm活动
当在流程中用[Confirm]调用其所对应的[CompensableActivity]的[ConfirmationHandler]时,[ConfirmationHandler]中的内容会被立即执行,这与自动调用不同
显式调用compensate活动
当在流程中用[Compensate]调用其所对应的[CompensableActivity]的[CompensationHandle]时,[CompensationHandle]中的内容会被立即执行,这与自动调用不同
显示调用[Compensate]时,不需要为 [实例.OnUnhandledException]指定[ UnhandledExceptionAction.Cancel]
6、多个/嵌套 CompensableActivity 容器
无异常时,如果有多个[CompensableActivity]或[CompensableActivity]有嵌套时,[ConfirmationHandler]执行顺序是:
在同级别容器中,是从下向上[ConfirmationHandler],在嵌套容器中是从外向内[ConfirmationHandler]
有异常,但异常不在CompensableActivity中时
如果有多个[CompensableActivity]或[CompensableActivity]有嵌套时,[ConfirmationHandler]与[CompensationHandler]执行顺序是:
6.1.如果产生异常的[Activity]与[CompensableActivity]在同级别容器中,则该级别的[CompensableActivity]会执行[ConfirmationHandler].
[CompensableActivity]嵌套的[CompensableActivity]会执行[ConfirmationHandler]
6.2、异常在CompensableActivity中时
如果有多个[CompensableActivity]或[CompensableActivity]有嵌套时,[ConfirmationHandler][CompensationHandler]与[CancellationHandler]执行顺序是:
*如果产生异常的[Activity]与[CompensableActivity]在同级别容器中,则该级别的[CompensableActivity]会执行[ConfirmationHandler].
[CompensableActivity]嵌套的[CompensableActivity]会执行[ConfirmationHandler]
*.如果产生异常的[Activity]与[CompensableActivity]具有[父子孙]的直接层级关系,会调用这些具有[父子孙]直接层级关系[CompensableActivity]的[CancellationHandler]
7、TerminateWorkflow 不会触发CompensableActivity的任何行为
官方实例
eg1简单的补偿活动
简介:在正常的执行顺序中,使用补偿活动给将要做的定义的工作。这个工作在晚点有必要去补偿这个动作。
相关知识点:
使用ManualResetEvent来创建一个线程供application来运行。
// Executing the sequence of two actions that complete with success
Console.WriteLine("Execution with success:");
application = new WorkflowApplication(BuildASequenceofCompensableActions());
ManualResetEvent resetEvent = new ManualResetEvent(false);
application.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
{
resetEvent.Set();
};
application.Run();
resetEvent.WaitOne();
eg2取消引发的补偿活动
简介:使用补偿范围来分组一系列可补偿的活动集,使它们与其他补偿范围相隔离。
相关知识点
CompensationToken,用来通过记录发放令牌来安排补偿活动的执行顺序。
eg3 客制化补偿
简介:使用补偿和补偿处理器来定义客制化的补偿逻辑。
eg4 分布式补偿
简介:使用补偿实现工作流服务宿主并行运作。
疑问:
CompensableActivity和Compensate的区别:前者是后者的集合。(有待验证)