/*
 * Copyright (c) 2023 codvision.com All Rights Reserved.
 */

package com.codvision.mqcore.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.codvision.mqcore.service.MQSender;
import com.codvision.mqcore.service.impl.MQSenderByRedis;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.redis.core.RedisTemplate;

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

/**
 * 启动redis延迟队列
 *
 * @author lingee
 * @date 2023/8/23
 */
@Slf4j
public class RedisDelayQueueRunner implements CommandLineRunner {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private MQSender mqSender;

    @Override
    public void run(String... args) throws Exception {
        new Thread(() -> {
            try {
                while (true) {
                    Set<String> keys = redisTemplate.keys(MQSenderByRedis.DELAYED_QUEUE_MSG_PREFIX + "*");
                    if (CollectionUtil.isEmpty(keys)) {
                        Thread.sleep(1000);
                        continue;
                    }
                    for (String key : keys) {
                        Set<Object> messages = redisTemplate.opsForZSet().rangeByScore(key, 0, System.currentTimeMillis());
                        if (messages != null && !messages.isEmpty()) {
                            Object message = messages.iterator().next();
                            mqSender.sendMessage(StrUtil.subAfter(key, MQSenderByRedis.DELAYED_QUEUE_MSG_PREFIX, true), message);
                            redisTemplate.opsForZSet().remove(key, message);
                        }
                    }
                }
            } catch (Exception e) {
                log.error("(Redis延迟队列异常中断) {}", e.getMessage());
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException ex) {
                    log.info(ex.getMessage(), ex);
                }
            }
        }).start();
    }
}
