package com.sinata.appointment.config;
|
|
import java.util.Map;
|
import java.util.concurrent.ThreadPoolExecutor;
|
import org.slf4j.MDC;
|
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Configuration;
|
import org.springframework.core.task.TaskDecorator;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
@Configuration
|
public class AsyncConfig {
|
|
@Bean(name = {"taskExecutor", "applicationTaskExecutor"})
|
public ThreadPoolTaskExecutor applicationTaskExecutor() {
|
return buildExecutor(4, 8, 200, "appointment-async-");
|
}
|
|
private ThreadPoolTaskExecutor buildExecutor(
|
int corePoolSize, int maxPoolSize, int queueCapacity, String threadNamePrefix) {
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
executor.setCorePoolSize(corePoolSize);
|
executor.setMaxPoolSize(maxPoolSize);
|
executor.setQueueCapacity(queueCapacity);
|
executor.setKeepAliveSeconds(60);
|
executor.setAllowCoreThreadTimeOut(true);
|
executor.setThreadNamePrefix(threadNamePrefix);
|
executor.setTaskDecorator(new MdcTaskDecorator());
|
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
executor.initialize();
|
return executor;
|
}
|
|
private static final class MdcTaskDecorator implements TaskDecorator {
|
|
@Override
|
public Runnable decorate(Runnable runnable) {
|
Map<String, String> contextMap = MDC.getCopyOfContextMap();
|
return () -> {
|
Map<String, String> previous = MDC.getCopyOfContextMap();
|
try {
|
if (contextMap == null || contextMap.isEmpty()) {
|
MDC.clear();
|
} else {
|
MDC.setContextMap(contextMap);
|
}
|
runnable.run();
|
} finally {
|
if (previous == null || previous.isEmpty()) {
|
MDC.clear();
|
} else {
|
MDC.setContextMap(previous);
|
}
|
}
|
};
|
}
|
}
|
}
|