项目使用SpringBoot + activiti6.0,使用multi databases scheme方式实现saas多租户。
在@configuration类中使用MultiSchemaMultiTenantProcessEngineConfiguration创建activiti process engine configuration @bean,然后异步执行使用SharedExecutorServiceAsyncExecutor类。
MultiSchemaMultiTenantProcessEngineConfigurationImpl engineConfig = new MultiSchemaMultiTenantProcessEngineConfigurationImpl(holder);
engineConfig.setAsyncExecutorActivate(true);
engineConfig.setAsyncExecutor(new SharedExecutorServiceAsyncExecutor(holder));
engineConfig.setDatabaseType(MultiSchemaMultiTenantProcessEngineConfiguration.DATABASE_TYPE_POSTGRES);
engineConfig.setDatabaseSchemaUpdate(MultiSchemaMultiTenantProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE);
然而,流程上的超时怎么也无法触发。
-----------------------
阅读了activiti源代码,发现activiti的acquireTimersJobs线程先会从act_ru_timers表中获取到即将执行的timers,然后将timers添加到act_ru_jobs表中,再由acquireAsyncJobs线程获取异步任务并触发任务。然而在执行触发前,DefaultJobManager都会询问process engine configuration上的asyncExecutor是否为active,而SharedExecutorServiceAsyncExecutor的active属性一直是false,也就无法触发任务了。
Class DefaultJobManager{
....
protected boolean isAsyncExecutorActive() {
return processEngineConfiguration.getAsyncExecutor().isActive();
}
....
}
源代码中SharedExecutorServiceAsyncExecutor的start()中,不会将active设置为true。
@Override
public void start() {
for (String tenantId : timerJobAcquisitionRunnables.keySet()) {
startTimerJobAcquisitionForTenant(tenantId);
startAsyncJobAcquisitionForTenant(tenantId);
startResetExpiredJobsForTenant(tenantId);
}
}
而父类DefaultAsyncJobExecutor的start方法,在启动后会将isActive属性设置为true。
public void start() {
if (isActive) {
return;
}
log.info("Starting up the default async job executor [{}].", getClass().getName());
if (timerJobRunnable == null) {
timerJobRunnable = new AcquireTimerJobsRunnable(this, processEngineConfiguration.getJobManager());
}
if (resetExpiredJobsRunnable == null) {
resetExpiredJobsRunnable = new ResetExpiredJobsRunnable(this);
}
if (!isMessageQueueMode && asyncJobsDueRunnable == null) {
asyncJobsDueRunnable = new AcquireAsyncJobsDueRunnable(this);
}
if (!isMessageQueueMode) {
initAsyncJobExecutionThreadPool();
startJobAcquisitionThread();
}
startTimerAcquisitionThread();
startResetExpiredJobsThread();
isActive = true;
executeTemporaryJobs();
}
是SharedExecutorServiceAsyncExecutor的bug吗?还是需要额外设置active?
--------
调研了好久也没找到方法,但找到activiti还提供另外一种DefaultAsyncJobExecutor的实现-ExecutorPerTenantAsyncExecutor。而它的start()方法中很明显将active设置为true了。
public class ExecutorPerTenantAsyncExecutor implements TenantAwareAsyncExecutor {
....
public void start() {
for (AsyncExecutor asyncExecutor : tenantExecutors.values()) {
asyncExecutor.start();
}
active = true;
}
.....
}
于是直接修改@configuration代码一试,流程定义上的timers触发了。
@Bean
public MultiSchemaMultiTenantProcessEngineConfiguration processEngineConfiguration(
TenantInfoHolder holder) throws Exception {
MultiSchemaMultiTenantProcessEngineConfigurationImpl engineConfig = new MultiSchemaMultiTenantProcessEngineConfigurationImpl(holder);
engineConfig.setAsyncExecutorActivate(true);
engineConfig.setAsyncExecutor(new ExecutorPerTenantAsyncExecutor(holder));
engineConfig.setDatabaseType(MultiSchemaMultiTenantProcessEngineConfiguration.DATABASE_TYPE_POSTGRES);
engineConfig.setDatabaseSchemaUpdate(MultiSchemaMultiTenantProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE);
return engineConfig;
}
----------
后话:关于activiti6.0实现multi tenant的网上资源不多,希望碰到类似问题的同学可以快速解决问题。
如果哪位老师知道SharedExecutorServiceAsyncExecutor的使用方法,希望可以回帖分享。