跳到主要内容

历史

Doubao 中英对照 History

历史(History)是捕获流程执行期间发生的事情并将其永久存储的组件。与运行时数据不同,即使在流程实例完成之后,历史数据仍会保留在数据库中。

历史共有 6 种实体:

  • HistoricProcessInstances:包含当前和过去流程实例的信息。
  • HistoricVariableInstances:包含流程变量或任务变量的最新值。
  • HistoricActivityInstances:包含某个活动(流程中的节点)单次执行的信息。
  • HistoricTaskInstances:包含当前和过去(已完成和已删除)任务实例的信息。
  • HistoricIdentityLinks:包含任务和流程实例上当前及过去身份链接的信息。
  • HistoricDetails:包含与历史流程实例、活动实例或任务实例相关的各类信息。

由于数据库中既包含历史实例实体,也包含正在运行的实例实体,你可能需要考虑查询这些表,以尽量减少对运行时流程实例数据的访问,从而保证运行时执行的性能。

查询历史​

在 API 中,可以查询全部 6 种历史实体。HistoryService 提供了方法 createHistoricProcessInstanceQuery()、createHistoricVariableInstanceQuery()、createHistoricActivityInstanceQuery()、getHistoricIdentityLinksForTask()、getHistoricIdentityLinksForProcessInstance()、createHistoricDetailQuery() 和 createHistoricTaskInstanceQuery()。

下面是几个示例,展示了历史查询 API 的部分能力。完整的能力说明可以在 javadocs 的 org.flowable.engine.history 包中找到。

HistoricProcessInstanceQuery​

获取定义为 'XXX' 的所有已完成流程中,耗时最长的 10 个已完成 HistoricProcessInstance。

historyService.createHistoricProcessInstanceQuery()
.finished()
.processDefinitionId("XXX")
.orderByProcessInstanceDuration().desc()
.listPage(0, 10);

HistoricVariableInstanceQuery​

从已完成的、id 为 'xxx' 的流程实例中获取所有 HistoricVariableInstance,并按变量名排序。

historyService.createHistoricVariableInstanceQuery()
.processInstanceId("XXX")
.orderByVariableName.desc()
.list();

HistoricActivityInstanceQuery​

获取在任何使用 id 为 XXX 的流程定义的流程中,已完成的类型为 'serviceTask' 的最近一个 HistoricActivityInstance。

historyService.createHistoricActivityInstanceQuery()
.activityType("serviceTask")
.processDefinitionId("XXX")
.finished()
.orderByHistoricActivityInstanceEndTime().desc()
.listPage(0, 1);

HistoricDetailQuery​

下一个示例获取在 id 为 123 的流程中完成的所有变量更新。该查询只返回 HistoricVariableUpdates。请注意,某个变量名可能对应多个 HistoricVariableUpdate 条目,对应流程中每次该变量被更新的时刻。你可以使用 orderByTime(变量更新发生的时间)或 orderByVariableRevision(更新时运行时变量的版本号)来弄清它们发生的顺序。

historyService.createHistoricDetailQuery()
.variableUpdates()
.processInstanceId("123")
.orderByVariableName().asc()
.list()

本示例获取在任意任务中或启动 id 为 "123" 的流程时提交的所有 form-properties。该查询只返回 HistoricFormProperties。

historyService.createHistoricDetailQuery()
.formProperties()
.processInstanceId("123")
.orderByVariableName().asc()
.list()

最后一个示例获取在 id 为 "123" 的任务上执行的所有变量更新。它返回在任务上设置的变量(任务局部变量)的所有 HistoricVariableUpdates,而不是流程实例上的。

historyService.createHistoricDetailQuery()
.variableUpdates()
.taskId("123")
.orderByVariableName().asc()
.list()

可以使用 TaskService 或在 TaskListener 内部的 DelegateTask 上设置任务局部变量:

taskService.setVariableLocal("123", "myVariable", "Variable value");

public void notify(DelegateTask delegateTask) {
delegateTask.setVariableLocal("myVariable", "Variable value");
}

HistoricTaskInstanceQuery​

获取所有任务中耗时最长的 10 个已完成 HistoricTaskInstance。

historyService.createHistoricTaskInstanceQuery()
.finished()
.orderByHistoricTaskInstanceDuration().desc()
.listPage(0, 10);

获取被删除的、删除原因中包含 "invalid"、且最后分配给用户 'kermit' 的 HistoricTaskInstance。

historyService.createHistoricTaskInstanceQuery()
.finished()
.taskDeleteReasonLike("%invalid%")
.taskAssignee("kermit")
.listPage(0, 10);

历史配置​

可以使用枚举 org.flowable.engine.impl.history.HistoryLevel(对于 5.11 之前的版本,则使用 ProcessEngineConfiguration 上定义的 HISTORY 常量)以编程方式配置历史级别:

ProcessEngine processEngine = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResourceDefault()
.setHistory(HistoryLevel.AUDIT.getKey())
.buildProcessEngine();

也可以在 flowable.cfg.xml 或 spring-context 中配置该级别:

<bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<property name="history" value="audit" />
...
</bean>

可以配置以下历史级别:

  • none:跳过所有历史归档。这对运行时流程执行而言性能最佳,但不会保留任何历史信息。
  • activity:归档所有流程实例和活动实例。在流程实例结束时,顶层流程实例变量的最新值将被复制到历史变量实例中。不归档任何细节。
  • audit:这是默认级别。它归档所有流程实例、活动实例,持续保持变量值同步,并归档所有提交的表单属性,从而使通过表单进行的所有用户交互都可追溯、可审计。
  • full:这是最高级别的历史归档,因此也是最慢的。该级别存储 audit 级别的所有信息以及所有其他可能的细节,主要是流程变量更新。

在旧版本中,历史级别存储在数据库中(表 ACT_GE_PROPERTY,属性名为 historyLevel)。从 5.11 开始,该值不再使用,并被从数据库中忽略/删除。现在可以在两次引擎启动之间更改历史级别,即使该级别与上一次引擎启动时不同,也不会抛出异常。

用于审计目的的历史​

当配置至少为 audit 级别时,通过方法 FormService.submitStartFormData(String processDefinitionId, Map<String, String> properties) 和 FormService.submitTaskFormData(String taskId, Map<String, String> properties) 提交的所有属性都会被记录下来。

可以像这样通过查询 API 获取表单属性:

historyService
.createHistoricDetailQuery()
.formProperties()
...
.list();

在这种情况下,只返回类型为 HistoricFormProperty 的历史细节。

如果你在调用提交方法之前使用 IdentityService.setAuthenticatedUserId(String) 设置了已认证用户,那么提交表单的该已认证用户也会在历史中可查:启动表单使用 HistoricProcessInstance.getStartUserId(),任务表单使用 HistoricActivityInstance.getAssignee()。

历史清理​

默认情况下历史数据会永久存储,这可能导致历史表变得非常庞大并影响 HistoryService 的性能。历史清理(History Cleaning)自 6.5.0 起引入,允许删除 HistoricProcessInstances 及其关联数据。一旦流程数据不再需要保留,就可以将其删除以减小历史数据库的体积。
历史流程的删除使用 Flowable Batch 机制完成:调度作业以分批方式删除流程,并将操作信息存储在批次表中。

自动历史清理配置​

HistoricProcessInstances 的自动清理默认是关闭的,但可以通过编程方式启用并配置。启用后,默认在凌晨 1 点运行清理作业,删除所有已结束满 365 天或更久的 HistoricProcessInstances 及关联数据。

ProcessEngine processEngine = ProcessEngineConfiguration
.createProcessEngineConfigurationFromResourceDefault()
.setEnableHistoryCleaning(true)
.setHistoryCleaningTimeCycleConfig("0 0 1 * * ?")
.setCleanInstancesEndedAfter(Duration.ofDays(365))
.buildProcessEngine();

在 application.properties 或外部化配置中设置的 Spring 属性同样可用:

     flowable.enable-history-cleaning=true
flowable.history-cleaning-after=365d
flowable.history-cleaning-cycle=0 0 1 * * ?

此外,历史清理也可以在 flowable.cfg.xml 或 spring-context 中配置:

 <bean id="processEngineConfiguration" class="org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<property name="enableHistoryCleaning" value="true"/>
<property name="historyCleaningTimeCycleConfig" value="0 0 1 * * ?"/>
<property name="cleanInstancesEndedAfterNumberOfDays" value="365"/>
...
</bean>

手动删除历史​

手动清理历史可以通过在 HistoryService 的查询构建器上执行相应方法来完成。

删除所有超过一年的 HistoricProcessInstances 及其相关数据。

 int numberOfProcessesInBatch = 10;
Calendar cal = new GregorianCalendar();
cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
historyService.createHistoricProcessInstanceQuery()
.finishedBefore(cal.getTime())
.deleteSequentiallyUsingBatch(numberOfProcessesInBatch, "Custom Delete Batch");