工作流持久性和书签作为工作流故障转移
本文关键字:工作流 故障 转移 书签 持久性 | 更新日期: 2023-09-27 17:54:58
我有一组自定义活动,用于复杂的工作流程。
我想使它们(自定义活动(持久化,而不会使工作流处于空闲状态。 它应该是一种故障转移系统,因此每当在执行工作流期间出现问题时,它可能是:
- 由用户暂停(
- 随时(,稍后从暂停的书签/点恢复(例如,用户注意到外部系统已关闭,他希望暂时暂停工作流(。
- 如果发生未经处理的异常,我们可以从最后一个书签/时间点重新开始执行
- 工作流应用程序主机的停止可以随时发生,我们可以从最后一个书签/时间点重新开始执行
我已经在工作流持久性方面工作了几天,但我不确定我是否可以实现我的目标。为什么?
- 我可以在每个自定义活动中使用阻止书签,但是阻止工作流并重新启动它只是为了持久保存它看起来并不乐观。
- 我可以使用notblock书签,但我无法在数据库中看到它们并从中恢复。
你能告诉我,工作流程书签是去这里的方式吗?
我在不阻止书签中看到了一些光芒,但我无法保留它们并在以后恢复。你能给我一些提示,如何保留一个非阻塞书签以供以后的简历吗?
编辑:
在 wf3 中,有一个属性PersistOnClose
足以满足我的要求。在 WF4 中,它被替换为Persist
活动,这也可能很有用,但我不想在我已经复杂的工作流中拥有额外的活动。
理想情况下,能够从NativeActivityContext
执行context.RequestPersist(callback)
会很棒,但是这种方法是内部的(并且它内部的所有内容在原始程序集之外都不可见。
这是我带来的:
- 非阻塞书签不是一种选择。尽管非阻塞书签不会阻止创建活动完成,但它也不会导致工作流实例变为空闲状态 - 这意味着它不会被保留。活动(创建书签(完成后,将丢弃非阻塞书签。仅当创建活动尚未完成时,才能恢复此书签。
- 使用
PersistOnCloseAttribute
不是一个选项,因为我使用的是 WF4,并且此属性只是 .NET 3.x WF。 - 不能使用阻止书签,因为它们会阻止工作流的执行,这是不需要的。
解决方案是在每个自定义活动中使用 Persist
活动(必须扩展NativeActivity
可以安排子活动(:
//class field
Activity childActivity = new Persist();
为了使它工作,必须将其作为ImplmentationChild添加到元数据中:
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
base.CacheMetadata(metadata);
metadata.AddImplementationChild(this.childActivity);
}
最后一件事是从 Execute 方法调度子活动(无论在哪里,持久性只会在调用活动完成后发生*(。
protected override void Execute(NativeActivityContext context)
{
//...
context.ScheduleActivity((Activity)this.childActivity);
}
为了在未处理的异常后保持工作流的持久性,必须将这段代码添加到 WorkflowApplication:
application.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
{
return UnhandledExceptionAction.Abort;
};
*从 Execute
方法返回并不一定意味着活动"已完成" - 即活动内部存在阻塞书签(请参阅下面的缺点(。
此解决方案有几个缺点:
- 解决方案仅保留工作流的一种状态(最后一个状态(。
- 持久性只能在活动完成时发生。这意味着无法从活动的中间进行持久/恢复。
- 它不适用于并行循环/序列 - 在整个并行操作完成后,来自并行循环/序列的活动将持久化。它与常规循环/序列一起正常工作。
- 阻止书签对此解决方案有巨大影响(如果它们是在创建活动或创建活动的其他子活动中创建的(。它们会导致活动未完成,即使返回了 Execute 方法也是如此。最终,持久将执行(在活动完成后或进入空闲状态之前(。
如果我理解你的问题正确,那么你有以下要求。
- 工作流的持久性和恢复。
- 用户可以暂停和恢复。
- 如果出现任何异常,工作流将保留并从下一个活动恢复。
您可以使用以下步骤。
- 可以使用 WF + WCF 服务来执行和承载工作流。
- 使用像SQL服务器这样的数据库添加持久性和跟踪,如果您使用的是oracle,则可以使用Devart。
- 将 ControlEnpont 配置为暂停和恢复。
- 明智地使用 try/捕获和持久性活动来处理异常。
如果有任何问题和需要自定义,请讨论相同.:)因为我开发了像您类似的工作流程。