Commit ecfe0b864b19671c15a384c3085e095e563cb874
1 parent
a978c996
优化 RedisPendingMessageResendJob 代码排版,以及注释
Showing
1 changed file
with
25 additions
and
18 deletions
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/job/RedisPendingMessageResendJob.java
| ... | ... | @@ -25,17 +25,18 @@ public class RedisPendingMessageResendJob { |
| 25 | 25 | |
| 26 | 26 | private static final String LOCK_KEY = "redis:pending:msg:lock"; |
| 27 | 27 | |
| 28 | + /** | |
| 29 | + * 消息超时时间,默认 5 分钟 | |
| 30 | + * | |
| 31 | + * 1. 超时的消息才会被重新投递 | |
| 32 | + * 2. 由于定时任务 1 分钟一次,消息超时后不会被立即重投,极端情况下消息5分钟过期后,再等 1 分钟才会被扫瞄到 | |
| 33 | + */ | |
| 34 | + private static final int EXPIRE_TIME = 5 * 60; | |
| 35 | + | |
| 28 | 36 | private final List<AbstractStreamMessageListener<?>> listeners; |
| 29 | 37 | private final RedisMQTemplate redisTemplate; |
| 30 | 38 | private final String groupName; |
| 31 | 39 | private final RedissonClient redissonClient; |
| 32 | - /** | |
| 33 | - * 消息超时时间,默认5分钟 | |
| 34 | - * <p>超时的消息才会被重新投递<p/> | |
| 35 | - * <p>由于定时任务1分钟一次,消息超时后不会被立即重投, | |
| 36 | - * 极端情况下消息5分钟过期后,再等1分钟才会被扫瞄到<p/> | |
| 37 | - */ | |
| 38 | - private final long expireTime = 5 * 60; | |
| 39 | 40 | |
| 40 | 41 | /** |
| 41 | 42 | * 一分钟执行一次,这里选择每分钟的35秒执行,是为了避免整点任务过多的问题 |
| ... | ... | @@ -55,6 +56,11 @@ public class RedisPendingMessageResendJob { |
| 55 | 56 | } |
| 56 | 57 | } |
| 57 | 58 | |
| 59 | + /** | |
| 60 | + * 执行清理逻辑 | |
| 61 | + * | |
| 62 | + * @see <a href="https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/480/files">讨论</a> | |
| 63 | + */ | |
| 58 | 64 | private void execute() { |
| 59 | 65 | StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream(); |
| 60 | 66 | listeners.forEach(listener -> { |
| ... | ... | @@ -65,28 +71,29 @@ public class RedisPendingMessageResendJob { |
| 65 | 71 | log.info("[processPendingMessage][消费者({}) 消息数量({})]", consumerName, pendingMessageCount); |
| 66 | 72 | // 每个消费者的 pending消息的详情信息 |
| 67 | 73 | PendingMessages pendingMessages = ops.pending(listener.getStreamKey(), Consumer.from(groupName, consumerName), Range.unbounded(), pendingMessageCount); |
| 68 | - if(pendingMessages.isEmpty()){ | |
| 74 | + if (pendingMessages.isEmpty()) { | |
| 69 | 75 | return; |
| 70 | 76 | } |
| 71 | - for (PendingMessage pendingMessage : pendingMessages) { | |
| 77 | + pendingMessages.forEach(pendingMessage -> { | |
| 72 | 78 | // 获取消息上一次传递到 consumer 的时间, |
| 73 | 79 | long lastDelivery = pendingMessage.getElapsedTimeSinceLastDelivery().getSeconds(); |
| 74 | - if(lastDelivery < expireTime){ | |
| 75 | - continue; | |
| 80 | + if (lastDelivery < EXPIRE_TIME){ | |
| 81 | + return; | |
| 76 | 82 | } |
| 77 | - // 获取指定id的消息体 | |
| 78 | - List<MapRecord<String, Object, Object>> records = ops.range(listener.getStreamKey(), Range.of(Range.Bound.inclusive(pendingMessage.getIdAsString()), Range.Bound.inclusive(pendingMessage.getIdAsString()))); | |
| 79 | - if(CollUtil.isEmpty(records)){ | |
| 80 | - continue; | |
| 83 | + // 获取指定 id 的消息体 | |
| 84 | + List<MapRecord<String, Object, Object>> records = ops.range(listener.getStreamKey(), | |
| 85 | + Range.of(Range.Bound.inclusive(pendingMessage.getIdAsString()), Range.Bound.inclusive(pendingMessage.getIdAsString()))); | |
| 86 | + if (CollUtil.isEmpty(records)) { | |
| 87 | + return; | |
| 81 | 88 | } |
| 82 | 89 | // 重新投递消息 |
| 83 | 90 | redisTemplate.getRedisTemplate().opsForStream().add(StreamRecords.newRecord() |
| 84 | - .ofObject(records.get(0).getValue()) // 设置内容 | |
| 85 | - .withStreamKey(listener.getStreamKey())); | |
| 91 | + .ofObject(records.get(0).getValue()) // 设置内容 | |
| 92 | + .withStreamKey(listener.getStreamKey())); | |
| 86 | 93 | // ack 消息消费完成 |
| 87 | 94 | redisTemplate.getRedisTemplate().opsForStream().acknowledge(groupName, records.get(0)); |
| 88 | 95 | log.info("[processPendingMessage][消息({})重新投递成功]", records.get(0).getId()); |
| 89 | - } | |
| 96 | + }); | |
| 90 | 97 | }); |
| 91 | 98 | }); |
| 92 | 99 | } | ... | ... |