事务

流程引擎以事务的方式执行流程。 BPMN 事务(transaction) 是一个逻辑工作单元,将一组活动组合在一起, 确保一组所有的活动都成功,或者如果任何活动失败, 则已完成的活动将通过补偿操作撤消。

事务是指当触发操作(例如启动流程、完成任务或发出执行信号)时, 引擎在流程中前进,直到在所有激活的执行路径上遇到等待状态。 更具体地说, 引擎在流程图中执行深度优先搜索, 并且在每个执行分支上都达到 等待状态 时返回。所有途径的活动都在一个事务中。 下图对此进行了说明:

transactions 1

我们可以看到,这是 BPMN 流程图的一部分,其中包含了一个用户任务、一个服务任务以及一个定时器任务。 用户任务和服务任务是同一工作单元的内容, 因此这两个任务应该以原子方式成功或失败。

即,如果服务任务抛出异常,我们必须回滚当前事务, 执行过程就会回溯到用户任务,并且用户任务仍然存在于数据库中。

在(1)中,应用程序或客户端线程完成任务。 在同一线程中, 流程引擎现在正在执行服务任务并前进,直到遇到等待状态, 在本例中,等待状态为定时器事件(2)。 然后它将控制权返回给调用者(3), 并提交事务。

等待状态

在 BPMN 中,一个 等待状态(waiting state) 指的是流程到达某个点时停止前进了, 需要等待一个事件或触发器才能继续。 这个状态可能由于各种原因发生,例如等待消息、定时器事件或用户输入。

流程中的等待状态包括:

  • 用户任务

  • 定时器事件

  • 消息捕获事件

  • 信号捕获事件

  • 带外部 worker 的服务任务

  • 基于事件的网关

异步延续

有时我们需要对流程中的事务边界进行自定义控制, 以便能够确定逻辑工作单元的范围。 这就是 异步延续(asynchronous continuations) 的作用。 在以下流程片段中:

transactions 2

在这个案例中,我们先完成用户任务,然后生成发票,最后将发票发送给客户。 这次,生成发票的任务与用户任务不在同一工作单元, 因此,如果生成发票失败,我们不希望回滚已经完成的用户任务。 我们希望流程引擎这么操作:完成用户任务(1), 提交事务并将控制权返回给调用应用程序。

然后,我们希望在后台异步线程中生成发票。 该后台线程是一个 作业执行器(实际上是一个线程池), 会定期轮询数据库查找需要处理的作业。 因此,实际当流程到达 “生成发票” 任务时,我们为流程引擎创建了一个需要生成作业的 “消息”, 告诉流程引擎稍后再继续流程并将作业写入数据库。 然后,该作业由作业执行器加载并执行。

如需使用此功能,必须设置 async 属性为 true

async property

在 XML 中,设置 flowable:async="true"

<serviceTask id="Activity_0pzv18b" name="Generate invoice"
 flowable:async="true" />

async 属性可用于:

失败重试

在 BPMN 中,失败重试(fail retry) 是指处理失败的服务任务的一种机制。 当任务由于发生错误而失败时, BPMN 引擎可以根据预定义的配置自动重试执行该任务。 配置有两个参数:

  • 重试次数

  • 重试间隔

如果任务返回 BPMN 错误,作业执行器将等待特定的时间,然后尝试再次执行该任务。 如果执行次数达到最大重试次数,但任务仍然失败,则会创建一个故障(incident), 可以进行手动干预或做进一步错误处理。

失败重试仅适用于异步任务。

对于同步服务任务,流程引擎不会处理重试。 当同步任务失败时,会抛出异常并停止流程实例。