package com.sw.mes.config;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author: GaoXinJian  |  liru
 * @Date: 2022-01-18 16:31   2024-02-03 23:27
 */
@Slf4j
@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {

    /**
     * 获取异步线程池执行对象
     *
     * @return
     */
    @Override
    public Executor getAsyncExecutor() {
        //使用Spring内置线程池任务对象
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //设置线程池参数
        taskExecutor.setCorePoolSize(10);
        // 最大线程数
        taskExecutor.setMaxPoolSize(30);
        // 等待队列(队列最大长度)
        taskExecutor.setQueueCapacity(1000);
        // 线程池维护线程所允许的空闲时间 ，单位s
        taskExecutor.setKeepAliveSeconds(300);
        
        //上下文子线程传递装饰器
        taskExecutor.setTaskDecorator(new ContextDecorator());
        
        taskExecutor.initialize();
        return taskExecutor;
    }
    
    
    @Bean(name = "sapGoodsmvtThreadTaskExecutor")
    public Executor sapGoodsmvtThreadTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(1); // 设置核心线程数为1，即单线程
        executor.setMaxPoolSize(1); // 设置最大线程数为1，虽然这个设置在单线程情况下是多余的，但为了保持配置的一致性可以设置
        executor.setQueueCapacity(2000); // 设置队列容量，任务会在队列中等待执行
        executor.setThreadNamePrefix("sapGoodsmvt-single-thread-"); // 可以设置线程名前缀，便于调试
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 使用调用者运行策略，当队列满时，主线程会直接运行任务
        executor.setTaskDecorator(new ContextDecorator());//线程继承上下文信息
        executor.initialize(); // 初始化执行器
        return executor;
    }
    
    
    @Bean(name = "sapWorkinghoursThreadTaskExecutor")
    public Executor sapWorkinghoursThreadTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(1); // 设置核心线程数为1，即单线程
        executor.setMaxPoolSize(1); // 设置最大线程数为1，虽然这个设置在单线程情况下是多余的，但为了保持配置的一致性可以设置
        executor.setQueueCapacity(2000); // 设置队列容量，任务会在队列中等待执行
        executor.setThreadNamePrefix("sapWorkinghours-single-thread-"); // 可以设置线程名前缀，便于调试
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 使用调用者运行策略，当队列满时，主线程会直接运行任务
        executor.setTaskDecorator(new ContextDecorator());//线程继承上下文信息
        executor.initialize(); // 初始化执行器
        return executor;
    }

    /**
     * 异步异常处理
     *
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SpringAsyncExceptionHandler();
    }

    class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
            log.error("Exception occurs in async method", throwable.getMessage());
        }
    }
}
