/*
 * 文 件 名:  AsyncConfig
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  异步任务执行器配置
 * 修 改 人:  lvwenbin
 * 修改时间:  2025/12/26
 * 修改内容:  配置全局异步任务线程池，解决内存溢出问题
 */
package com.ruoyi.ems.common.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
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 java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 异步任务执行器配置
 * 替换Spring默认的SimpleAsyncTaskExecutor，使用线程池管理异步任务
 * 防止因频繁创建线程导致的内存溢出
 *
 * @author lvwenbin
 * @version [版本号, 2025/12/26]
 */
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    private static final Logger log = LoggerFactory.getLogger(AsyncConfig.class);

    @Value("${async.executor.corePoolSize:4}")
    private int corePoolSize;

    @Value("${async.executor.maxPoolSize:8}")
    private int maxPoolSize;

    @Value("${async.executor.queueCapacity:500}")
    private int queueCapacity;

    @Value("${async.executor.threadNamePrefix:async-task-}")
    private String threadNamePrefix;

    @Override
    @Bean(name = "taskExecutor")
    public Executor getAsyncExecutor() {
        log.info("初始化全局异步任务线程池 taskExecutor");
        log.info("配置: corePoolSize={}, maxPoolSize={}, queueCapacity={}, namePrefix={}",
                corePoolSize, maxPoolSize, queueCapacity, threadNamePrefix);

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix(threadNamePrefix);

        executor.setKeepAliveSeconds(60);
        executor.setAllowCoreThreadTimeOut(true);

        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);

        executor.initialize();

        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, params) -> {
            log.error("异步任务执行异常 - 方法: {}, 异常: {}", method.getName(), throwable.getMessage(), throwable);
        };
    }
}
