事务
流程引擎以事务的方式执行流程。 BPMN 事务(transaction) 是一个逻辑工作单元,将一组活动组合在一起, 确保一组所有的活动都成功,或者如果任何活动失败, 则已完成的活动将通过补偿操作撤消。
事务是指当触发操作(例如启动流程、完成任务或发出执行信号)时, 引擎在流程中前进,直到在所有激活的执行路径上遇到等待状态。 更具体地说, 引擎在流程图中执行深度优先搜索, 并且在每个执行分支上都达到 等待状态 时返回。所有途径的活动都在一个事务中。 下图对此进行了说明:
我们可以看到,这是 BPMN 流程图的一部分,其中包含了一个用户任务、一个服务任务以及一个定时器任务。 用户任务和服务任务是同一工作单元的内容, 因此这两个任务应该以原子方式成功或失败。
即,如果服务任务抛出异常,我们必须回滚当前事务, 执行过程就会回溯到用户任务,并且用户任务仍然存在于数据库中。
在(1)中,应用程序或客户端线程完成任务。 在同一线程中, 流程引擎现在正在执行服务任务并前进,直到遇到等待状态, 在本例中,等待状态为定时器事件(2)。 然后它将控制权返回给调用者(3), 并提交事务。
等待状态
在 BPMN 中,一个 等待状态(waiting state) 指的是流程到达某个点时停止前进了, 需要等待一个事件或触发器才能继续。 这个状态可能由于各种原因发生,例如等待消息、定时器事件或用户输入。
流程中的等待状态包括:
-
用户任务
-
定时器事件
-
消息捕获事件
-
信号捕获事件
-
带外部 worker 的服务任务
-
基于事件的网关
异步延续
有时我们需要对流程中的事务边界进行自定义控制, 以便能够确定逻辑工作单元的范围。 这就是 异步延续(asynchronous continuations) 的作用。 在以下流程片段中:
在这个案例中,我们先完成用户任务,然后生成发票,最后将发票发送给客户。 这次,生成发票的任务与用户任务不在同一工作单元, 因此,如果生成发票失败,我们不希望回滚已经完成的用户任务。 我们希望流程引擎这么操作:完成用户任务(1), 提交事务并将控制权返回给调用应用程序。
然后,我们希望在后台异步线程中生成发票。 该后台线程是一个 作业执行器(实际上是一个线程池), 会定期轮询数据库查找需要处理的作业。 因此,实际当流程到达 “生成发票” 任务时,我们为流程引擎创建了一个需要生成作业的 “消息”, 告诉流程引擎稍后再继续流程并将作业写入数据库。 然后,该作业由作业执行器加载并执行。
如需使用此功能,必须设置 async
属性为 true
。
在 XML 中,设置 flowable:async="true"
。
<serviceTask id="Activity_0pzv18b" name="Generate invoice"
flowable:async="true" />
async
属性可用于:
失败重试
在 BPMN 中,失败重试(fail retry) 是指处理失败的服务任务的一种机制。 当任务由于发生错误而失败时, BPMN 引擎可以根据预定义的配置自动重试执行该任务。 配置有两个参数:
-
重试次数
-
重试间隔
如果任务返回 BPMN 错误,作业执行器将等待特定的时间,然后尝试再次执行该任务。 如果执行次数达到最大重试次数,但任务仍然失败,则会创建一个故障(incident), 可以进行手动干预或做进一步错误处理。
失败重试仅适用于异步任务。 |
对于同步服务任务,流程引擎不会处理重试。 当同步任务失败时,会抛出异常并停止流程实例。 |