FINERACT-2449: Replace unbounded SimpleAsyncTaskExecutor with ThreadPoolTaskExecutor
This commit is contained in:
+46
-12
@@ -19,34 +19,68 @@
|
||||
|
||||
package org.apache.fineract.infrastructure.core.config;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
||||
import org.springframework.boot.task.ThreadPoolTaskExecutorBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.context.event.SimpleApplicationEventMulticaster;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor;
|
||||
|
||||
@Configuration
|
||||
public class SpringConfig {
|
||||
|
||||
private static final int AWAIT_TERMINATION_SECONDS = 60;
|
||||
private static final int DEFAULT_QUEUE_CAPACITY = 100;
|
||||
|
||||
@Bean(name = "fineractEventExecutor")
|
||||
public ThreadPoolTaskExecutor fineractEventExecutor(ThreadPoolTaskExecutorBuilder builder,
|
||||
@Value("${spring.task.execution.pool.core-size:-1}") int configuredCore,
|
||||
@Value("${spring.task.execution.pool.max-size:-1}") int configuredMax,
|
||||
@Value("${spring.task.execution.pool.queue-capacity:-1}") int configuredQueueCapacity) {
|
||||
|
||||
int cpus = Runtime.getRuntime().availableProcessors();
|
||||
int smartCore = cpus * 2;
|
||||
int smartMax = cpus * 5;
|
||||
|
||||
int coreSize = configuredCore > 0 ? configuredCore : smartCore;
|
||||
int rawMaxSize = configuredMax > 0 ? configuredMax : smartMax;
|
||||
int queueCapacity = configuredQueueCapacity >= 0 ? configuredQueueCapacity : DEFAULT_QUEUE_CAPACITY;
|
||||
|
||||
int finalMaxSize = Math.max(rawMaxSize, coreSize);
|
||||
|
||||
ThreadPoolTaskExecutor executor = builder.threadNamePrefix("FineractEvent-").corePoolSize(coreSize).maxPoolSize(finalMaxSize)
|
||||
.queueCapacity(queueCapacity).build();
|
||||
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||
executor.setAwaitTerminationSeconds(AWAIT_TERMINATION_SECONDS);
|
||||
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SimpleApplicationEventMulticaster applicationEventMulticaster() {
|
||||
SimpleApplicationEventMulticaster saem = new SimpleApplicationEventMulticaster();
|
||||
saem.setTaskExecutor(new SimpleAsyncTaskExecutor());
|
||||
return saem;
|
||||
@DependsOn("overrideSecurityContextHolderStrategy")
|
||||
public SimpleApplicationEventMulticaster applicationEventMulticaster(
|
||||
@Qualifier("fineractEventExecutor") ThreadPoolTaskExecutor taskExecutor) {
|
||||
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
|
||||
multicaster.setTaskExecutor(new DelegatingSecurityContextAsyncTaskExecutor(taskExecutor));
|
||||
return multicaster;
|
||||
}
|
||||
|
||||
// The application events (for importing) rely on the inheritable thread local security context strategy
|
||||
// This is NOT compatible with threadpools so if we use threadpools the below will need to be reworked
|
||||
@Bean
|
||||
public MethodInvokingFactoryBean overrideSecurityContextHolderStrategy() {
|
||||
MethodInvokingFactoryBean mifb = new MethodInvokingFactoryBean();
|
||||
mifb.setTargetClass(SecurityContextHolder.class);
|
||||
mifb.setTargetMethod("setStrategyName");
|
||||
mifb.setArguments("MODE_INHERITABLETHREADLOCAL");
|
||||
return mifb;
|
||||
MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean();
|
||||
factoryBean.setTargetClass(SecurityContextHolder.class);
|
||||
factoryBean.setTargetMethod("setStrategyName");
|
||||
factoryBean.setArguments(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
|
||||
return factoryBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user