package com.qmth.jkserver.core.config;

import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.model.SysConfig;
import com.qmth.jkserver.service.CommonCacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Description: 线程池配置
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/5/11
 */
@Configuration
public class ExecutorConfig implements AsyncConfigurer {
    private final static Logger log = LoggerFactory.getLogger(ExecutorConfig.class);
    private ThreadPoolTaskExecutor executor = null;
    static final int cpuNum = Runtime.getRuntime().availableProcessors();

    @Resource
    CommonCacheService commonCacheService;

    @Override
    public Executor getAsyncExecutor() {
        SysConfig sysConfigCustomThreadPoolCoreSize = commonCacheService.addSysConfigCache(SystemConstant.CUSTOM_THREAD_POOL_CORE_SIZE);
        Optional.ofNullable(sysConfigCustomThreadPoolCoreSize).orElseThrow(() -> new JkServerException("未配置是否自定义线程池大小"));
        boolean customThreadPoolCoreSize = Boolean.valueOf(sysConfigCustomThreadPoolCoreSize.getConfigValue());

        SysConfig sysConfigThreadPoolCoreSize = commonCacheService.addSysConfigCache(SystemConstant.THREAD_POOL_CORE_SIZE);
        Optional.ofNullable(sysConfigThreadPoolCoreSize).orElseThrow(() -> new JkServerException("未配置自定义线程池大小"));
        Integer threadPoolCoreSize = Integer.valueOf(sysConfigThreadPoolCoreSize.getConfigValue());

        if (Objects.isNull(executor)) {
            log.info("cpuNum:{}", cpuNum);
            executor = new ThreadPoolTaskExecutor();
            if (!customThreadPoolCoreSize && cpuNum > 0) {
                executor.setCorePoolSize(cpuNum);//核心线程数
                executor.setMaxPoolSize(cpuNum * 2);//最大线程数
            } else {
                executor.setCorePoolSize(threadPoolCoreSize);//核心线程数
                executor.setMaxPoolSize(threadPoolCoreSize * 2);//最大线程数
            }
            executor.setKeepAliveSeconds(SystemConstant.THREAD_POOL_KEEP_ALIVE_SECONDS);//线程空闲时间
            executor.setQueueCapacity(SystemConstant.THREAD_POOL_QUEUE_CAPACITY);//队列容量
            executor.setThreadNamePrefix(SystemConstant.THREAD_POOL_NAME);
            executor.setAllowCoreThreadTimeOut(true);//设置是否允许核心线程超时。若允许，核心线程超时后，会被销毁。默认为不允许（fasle）
            executor.setWaitForTasksToCompleteOnShutdown(true);//设置shutdown时是否等到所有任务完成再真正关闭
            executor.setAwaitTerminationSeconds(60);//当setWaitForTasksToCompleteOnShutdown(true)时，setAwaitTerminationSeconds 设置在 shutdown 之后最多等待多长时间后再真正关闭线程池
            // rejection-policy：当pool已经达到max size的时候，如何处理新任务
            // CALLER_RUNS：不在新线程中执行任务，而是由调用者所在的线程来执行
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            executor.initialize();
        }
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}
