All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.kaizen4j.redis.message.DefaultRedisMessageTemplate Maven / Gradle / Ivy

The newest version!
package com.github.kaizen4j.redis.message;

import com.github.kaizen4j.redis.connection.DelayMessage;
import com.github.kaizen4j.redis.connection.MessageConfig;
import com.github.kaizen4j.util.PrimitiveUtils;
import com.google.common.base.Preconditions;
import java.sql.Timestamp;
import java.time.Duration;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;

/**
 * @author liuguowen
 */
@SuppressWarnings("unchecked")
public class DefaultRedisMessageTemplate implements RedisMessageTemplate {

    private static final Logger logger = LoggerFactory.getLogger(DefaultRedisMessageTemplate.class);

    private RedisTemplate redisTemplate;

    private MessageConfig messageConfig;

    public DefaultRedisMessageTemplate(RedisTemplate redisTemplate, MessageConfig messageConfig) {
        this.redisTemplate = redisTemplate;
        this.messageConfig = messageConfig;
    }

    @Override
    public boolean publishMessage(DelayMessage delayMessage) {
        Preconditions.checkNotNull(delayMessage.getDuration(), "Message delay time must not be null");
        try {
            if (this.putMessageBody(delayMessage)) {
                return this.putMessageId(delayMessage);
            }
        } catch (Exception e) {
            logger.error("DelayMessage [{}] join queue failed", delayMessage, e);
        }
        return false;
    }

    private Boolean putMessageId(DelayMessage delayMessage) {
        long score = delayMessage.getDuration().plusMillis(System.currentTimeMillis()).toMillis();
        BoundZSetOperations zSetOperations = redisTemplate
                .boundZSetOps(delayMessage.getChannelString());
        Boolean result = zSetOperations.add(delayMessage.getMessageId(), score);

        logger.info("DelayMessage join queue on topic [{}] with id [{}] result [{}] delay time [{}] ",
                delayMessage.getChannelString(), delayMessage.getMessageId(), result, new Timestamp(score));
        return result;
    }

    private Boolean putMessageBody(DelayMessage delayMessage) {
        String bodyKey = messageConfig.getMessageBodyCacheKey(delayMessage.getMessageId());
        Duration cacheSeconds = delayMessage.getDuration().plusSeconds(messageConfig.getMessageBodyCacheSeconds());
        redisTemplate.opsForValue().set(bodyKey, delayMessage.getBodyString(), cacheSeconds);
        // 初始化 ACK
        String ackKey = messageConfig.getMessageAckCacheKey(delayMessage.getMessageId());
        redisTemplate.opsForValue().set(ackKey, 0, cacheSeconds);

        logger.info("Cache DelayMessage [{}] expired seconds [{}]", delayMessage, cacheSeconds);
        return Boolean.TRUE.equals(redisTemplate.hasKey(bodyKey));
    }

    @Override
    public boolean publishMessage(String topic, String message) {
        try {
            redisTemplate.convertAndSend(topic, message);
            logger.info("Publish subscription message on topic [{}] body [{}]", topic, message);
            return true;
        } catch (Exception e) {
            logger.error("Publish subscription message failed on topic [{}] body [{}] ", topic, message, e);
            return false;
        }
    }

    @Override
    public boolean removeMessage(String topic, String messageId) {
        boolean a = this.removeMessageId(topic, messageId);
        boolean b = this.removeMessageBodyAndAck(messageId);
        return a && b;
    }

    private Boolean removeMessageBodyAndAck(String messageId) {
        String bodyKey = messageConfig.getMessageBodyCacheKey(messageId);
        boolean a = Boolean.TRUE.equals(redisTemplate.delete(bodyKey));
        if (logger.isDebugEnabled()) {
            logger.debug("Remove message body [{}] with id [{}] result [{}]", bodyKey, messageId, a);
        }

        String ackKey = messageConfig.getMessageAckCacheKey(messageId);
        boolean b = Boolean.TRUE.equals(redisTemplate.delete(ackKey));
        if (logger.isDebugEnabled()) {
            logger.debug("Remove message ack [{}] with id [{}] result [{}]", ackKey, messageId, b);
        }
        return a && b;
    }

    private boolean removeMessageId(String topic, String messageId) {
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        Long count = zSetOperations.remove(topic, messageId);
        if (logger.isDebugEnabled()) {
            logger.debug("Remove message id [{}] on topic [{}] result [{}]", messageId, topic, count);
        }
        return 0 != PrimitiveUtils.getValue(count, 0);
    }

    @Override
    public String getMessageBody(String messageId) {
        String bodyKey = messageConfig.getMessageBodyCacheKey(messageId);
        ValueOperations valueOperations = redisTemplate.opsForValue();
        return valueOperations.get(bodyKey);
    }

    @Override
    public long getMessageAck(String messageId) {
        String ackKey = messageConfig.getMessageAckCacheKey(messageId);
        ValueOperations valueOperations = redisTemplate.opsForValue();
        Object ackValue = valueOperations.get(ackKey);
        return Objects.nonNull(ackValue) ? Long.valueOf(ackValue.toString()) : 0L;
    }

    @Override
    public boolean acknowledge(String topic, String messageId) {
        try {
            String ackKey = messageConfig.getMessageAckCacheKey(messageId);
            ValueOperations valueOperations = redisTemplate.opsForValue();
            Long count = valueOperations.increment(ackKey);

            logger.info("Do acknowledge on topic [{}] DelayMessage id [{}] result [{}]", topic, messageId, count);
            return 0 != PrimitiveUtils.getValue(count, 0);
        } catch (Exception e) {
            logger.error("Do acknowledge failed on topic [{}] DelayMessage id [{}] ", topic, messageId, e);
            return false;
        }
    }

    @Override
    public boolean acknowledge(DelayMessage message) {
        return acknowledge(message.getChannelString(), message.getMessageId());
    }

    @Override
    public RedisTemplate getRedisTemplate() {
        return this.redisTemplate;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy