package com.jianshui.queue.container;


import com.jianshui.queue.consumer.RedisQueueConsumer;
import com.jianshui.queue.listener.RedisQueueListener;
import com.jianshui.queue.threadpoll.RedisQueueThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description redis queue 消费者容器
 * @Author 巩权林
 * @Date 2021-11-25 9:50
 **/
public class RedisQueueConsumerContainer {

    protected final Logger log = LoggerFactory.getLogger(RedisQueueListener.class);

    //存放消费者的map  key=消费者 queueName value=消费者对象
    Map<String, RedisQueueConsumer> consumerMap = new HashMap<>();

    // 容器是否初始化完毕的标示
    public static Boolean isRun = false;
    RedisQueueThreadPool myRedisThreadPool;

    public void addConsumer(RedisQueueConsumer consumer) {
        if (consumer.getQueueName() == null) {
            log.error("【添加redis队列失败】:{}", "队列名称为null");
        } else if (null == consumerMap.get(consumer.getQueueName())) {
            consumerMap.put(consumer.getQueueName(), consumer);
            log.error("【添加redis队列成功】:{}", consumer.getQueueName());
        }
    }

    public void destroy() {
        log.info("【redis队列】redis消费者容器销毁");
        myRedisThreadPool.destroy();
    }

    public void init() {
        log.info("【redis队列】redis消费者容器初始化开始");
        isRun = true;
        int cores = Runtime.getRuntime().availableProcessors();
        myRedisThreadPool = RedisQueueThreadPool.getInstance(4 * cores + 2);
        // myRedisThreadPool = RedisQueueThreadPool.getInstance(consumerMap.size());
        consumerMap.forEach((k, v) -> {
            myRedisThreadPool.executor(new RedisQueueListener(v));
        });
    }

    public static int getBestPoolSize() {
        try {
            // JVM可用处理器的个数
            final int cores = Runtime.getRuntime().availableProcessors();
            // 最佳的线程数 = CPU可用核心数 / (1 - 阻塞系数)
            // TODO 阻塞系数是不是需要有个setter方法能让使用者自由设置呢？
            return (int) (cores / (1 - 0.9));
        } catch (Throwable e) {
            // 异常发生时姑且返回10个任务线程池
            return 10;
        }
    }
}
