package com.yiqi.task;

import com.yiqi.common.core.redis.RedisUtils;
import com.yiqi.delay.DelayMessage;
import com.yiqi.delay.DelayQueueCache;
import com.yiqi.delay.impl.DelayTaskRunService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;
import java.util.concurrent.ExecutorService;

/**
 * @author douya
 * @description 延迟队列消息监听执行器
 * @date 2022/5/19
 */
@Component
public class OrderPayDelayQueueTask {

    protected final Logger logger = LoggerFactory.getLogger(OrderPayDelayQueueTask.class);

    @Resource
    private DelayQueueCache delayQueueCache;

    @Resource
    private RedisUtils redisUtils;

    @Resource(name = "delayTaskExecutor")
    private ExecutorService executor;
    @Resource
    private DelayTaskRunService delayTaskRunService;

    /**
     * 延时队列机器开始运作，发送消息给到消息队列
     */
    @Scheduled(fixedDelay = 1000)
    private void startDelayQueue() {
        long now = System.currentTimeMillis() / 1000;
        //获取当前时间前需要执行的任务列表
        Set<Object> tuples = redisUtils.zRangeByScore("DELAY_TASK_CACHE", 0, now);
        //如果任务不为空
        if (tuples != null) {
            for (Object tuple : tuples) {
                //移除缓存，如果移除成功则表示当前线程处理了延时任务，则执行延时任务
                DelayMessage delayMessage = delayQueueCache.getDelayMessageByKey(tuple.toString());
                if (delayMessage == null) {
                    redisUtils.zRemove("DELAY_TASK_CACHE", tuple.toString());
                    continue;
                }
                //暂不执行请求，如果超过60S还未启动，可能存在系统故障，则重新开启
                if (delayMessage.getIsRun() == 0) {
                    Long between = now - delayMessage.getRunTime();
                    if (between < 60) {
                        continue;
                    }
                }
                executor.submit(new Runnable() {
                    @Override
                    public void run() {
                        delayTaskRunService.handleDelayMessage(delayMessage.getTags(), delayMessage);
                    }
                });
            }
        }
    }
}
