package com.jeequan.jeepay.components.mq.executor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * MQ 线程池配置
 *
 * @author terrfly
 *
 * @date 2021/6/8 17:33
 */
@Configuration
@EnableAsync
public class MqThreadExecutor {

    /**
     * 商户进件处理
     */
    public static final String EXECUTOR_MCH_AUDIT = "mqQueue4MchAuditExecutor";

    /**
     * 通用的线程池,一般不与外部接口交互的都可使用该线程池
     */
    public static final String EXECUTOR_COMMON = "mqQueue4CommonExecutor";
    /**
     * 商户订单通知处理线程池
     */
    public static final String EXECUTOR_PAY_ORDER_MCH_NOTIFY = "mqQueue4PayOrderMchNotifyExecutor";
    /**
     * APP推送处理线程池
     */
    public static final String EXECUTOR_APP_PUSH = "mqQueue4AppPushExecutor";
    /**
     * 订单分账处理线程池
     */
    public static final String EXECUTOR_PAY_ORDER_DIVISION = "mqQueue4PayOrderDivisionExecutor";
    /**
     * 订单补单处理线程池
     */
    public static final String EXECUTOR_PAY_ORDER_REISSUE = "mqQueue4PayOrderReissueExecutor";
    /**
     * 推送云打印处理线程池
     */
    public static final String EXECUTOR_PUSH_PRINTER = "mqQueue4PushPrinterExecutor";
    /**
     * 推送云播报处理线程池
     */
    public static final String EXECUTOR_PUSH_SPEAKER = "mqQueue4PushSpeakerExecutor";
    /**
     * 推送公众号消息处理线程池
     */
    public static final String EXECUTOR_PUSH_MP_MSG = "mqQueue4PushWxMpMsgExecutor";
    /**
     * 直付通结算订单处理线程池
     */
    public static final String EXECUTOR_ZFT_SETT_ORDER = "mqQueue4ZftSettOrderExecutor";
    /**
     * 订单支付成功自动提现线程池
     */
    public static final String EXECUTOR_PAY_ORDER_CASHOUT = "mqQueue4PayOrderCashoutExecutor";

    /**
     * 账户余额线程池
     */
    public static final String EXECUTOR_ACCOUNT_BALANCE = "mqQueue4AccountBalanceExecutor";

    /**
     * 订单营销活动线程池
     */
    public static final String EXECUTOR_PAY_ORDER_MARKET = "mqQueue4PayOrderMarketExecutor";


    /**
     * 默认核心线程数量
     */
    private static final int DEFAULT_CORE_POOL_SIZE = 10;
    /**
     * 默认最大线程数量
     */
    private static final int DEFAULT_MAX_POOL_SIZE = 50;
    /**
     * 缓存队列
     */
    private static final int DEFAULT_QUEUE_CAPACITY = 200;
    /**
     * 允许的空闲时间，单位秒
     */
    private static final int DEFAULT_KEEP_ALIVE_SECONDS = 60;

    @Bean
    public Executor mqQueue4CommonExecutor() {
        return createExecutor(EXECUTOR_COMMON, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4MchAuditExecutor() {
        return createExecutor(EXECUTOR_MCH_AUDIT, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }



    @Bean
    public Executor mqQueue4PayOrderMchNotifyExecutor() {
        return createExecutor(EXECUTOR_PAY_ORDER_MCH_NOTIFY, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4AppPushExecutor() {
        return createExecutor(EXECUTOR_APP_PUSH, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4PayOrderDivisionExecutor() {
        return createExecutor(EXECUTOR_PAY_ORDER_DIVISION, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4PayOrderReissueExecutor() {
        return createExecutor(EXECUTOR_PAY_ORDER_REISSUE, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4PushPrinterExecutor() {
        return createExecutor(EXECUTOR_PUSH_PRINTER, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4PushSpeakerExecutor() {
        return createExecutor(EXECUTOR_PUSH_SPEAKER, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4PushWxMpMsgExecutor() {
        return createExecutor(EXECUTOR_PUSH_MP_MSG, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4ZftSettOrderExecutor() {
        return createExecutor(EXECUTOR_ZFT_SETT_ORDER, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4PayOrderCashoutExecutor() {
        return createExecutor(EXECUTOR_PAY_ORDER_CASHOUT, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4AccountBalanceExecutor() {
        return createExecutor(EXECUTOR_ACCOUNT_BALANCE, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    @Bean
    public Executor mqQueue4PayOrderMarketExecutor() {
        return createExecutor(EXECUTOR_PAY_ORDER_MARKET, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAX_POOL_SIZE, DEFAULT_QUEUE_CAPACITY, DEFAULT_KEEP_ALIVE_SECONDS);
    }

    /**
     * 创建 Executor
     * @param threadNamePrefix  线程名称的前缀
     * @param corePoolSize      核心线程数, 根据机器的配置进行添加
     * @param maxPoolSize       最大线程数
     * @param queueCapacity     缓存队列，缓存队列尽量减少，否则将堵塞在队列中无法执行
     * @param keepAliveSeconds  允许的空闲时间
     * @return
     */
    protected Executor createExecutor(String threadNamePrefix, int corePoolSize, int maxPoolSize, int queueCapacity, int keepAliveSeconds) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix(threadNamePrefix);
        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
        // CALLER_RUNS：不在新线程中执行任务，而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.initialize();
        return executor;
    }

}
