diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/retry/MessageRetryQueueServiceImpl.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/retry/MessageRetryQueueServiceImpl.java index 5184e74..9e371cf 100644 --- a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/retry/MessageRetryQueueServiceImpl.java +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/retry/MessageRetryQueueServiceImpl.java @@ -19,7 +19,6 @@ import com.njcn.msgpush.module.push.service.message.MessageRecordService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; -import org.springframework.dao.DuplicateKeyException; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -49,11 +48,6 @@ public class MessageRetryQueueServiceImpl extends ServiceImpl INTERMEDIATE_STATES = Arrays.asList( - MsgStatusConstant.SENDING, - MsgStatusConstant.PENDING, - MsgStatusConstant.RETRYABLE_FAILED); private static final List CHANNELS = Arrays.asList( ChannelTypeEnum.SMS.getCode(), @@ -77,34 +71,24 @@ public class MessageRetryQueueServiceImpl extends ServiceImpl() - .eq(MessageRetryQueueDO::getMessageId, message.getId())); - if (concurrent != null) { - applyRetryUpdate(message, concurrent); - } + MessageRetryQueueDO retryRecord = new MessageRetryQueueDO(); + retryRecord.setMessageId(message.getId()); + retryRecord.setChannel(message.getChannel()); + retryRecord.setReceiver(message.getReceiver()); + retryRecord.setRetryCount(1); + RetryStrategyConfigDO strategyConfig = retryStrategyConfigService.getStrategyConfig(message.getChannel()); + retryRecord.setMaxRetry(ObjectUtil.isNull(strategyConfig) ? DEFAULT_MAX_RETRY_COUNT : strategyConfig.getMaxRetryCount()); + retryRecord.setFirstFailTime(message.getSendTime()); + retryRecord.setLastRetryTime(message.getSendTime()); + retryRecord.setLastErrorMsg(message.getErrorMsg()); + LocalDateTime nextRetryTime = calculateNextRetryTime(message.getChannel(), retryRecord.getRetryCount(), isRateLimit(message)); + retryRecord.setNextRetryTime(nextRetryTime); + retryRecord.setProcessStatus(PROCESS_STATUS_WAITING); + retryRecord.setLockUntil(null); + message.setNextRetryTime(nextRetryTime); + save(retryRecord); + if (!messageRetryRedisDAO.addToRetryQueue(message)) { + log.warn("消息已写入数据库重试队列,但 Redis 入队失败: messageId={}", message.getId()); } return; } @@ -159,11 +143,6 @@ public class MessageRetryQueueServiceImpl extends ServiceImpl= RATE_LIMIT_MAX_DURATION_SECONDS; } - /** 是否终态(默认删):不在白名单中间态里即为终态 */ - static boolean isTerminalState(String status) { - return !INTERMEDIATE_STATES.contains(status); - } - LocalDateTime calculateNextRetryTime(String channel, int retryCount, boolean rateLimit) { if (rateLimit) { return LocalDateTime.now().plusSeconds(RATE_LIMIT_INTERVAL_SECONDS); @@ -251,8 +230,8 @@ public class MessageRetryQueueServiceImpl extends ServiceImpl 1; - --- 2) 加唯一约束(确认上面无重复后再执行) -ALTER TABLE push_message_retry_queue - ADD CONSTRAINT uk_pmrq_message_id UNIQUE (message_id); diff --git a/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/service/retry/RetryDecisionLogicTest.java b/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/service/retry/RetryDecisionLogicTest.java index 78018a2..0dff716 100644 --- a/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/service/retry/RetryDecisionLogicTest.java +++ b/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/service/retry/RetryDecisionLogicTest.java @@ -1,13 +1,11 @@ package com.njcn.msgpush.module.push.service.retry; -import com.njcn.msgpush.module.push.constant.MsgStatusConstant; import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO; import org.junit.jupiter.api.Test; import java.time.Duration; import java.time.LocalDateTime; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -48,24 +46,6 @@ class RetryDecisionLogicTest { assertTrue(MessageRetryQueueServiceImpl.isRateLimitExhausted(now.minusSeconds(43201), now)); } - @Test - void isTerminalState_intermediatesAreNotTerminal() { - assertFalse(MessageRetryQueueServiceImpl.isTerminalState(MsgStatusConstant.SENDING)); - assertFalse(MessageRetryQueueServiceImpl.isTerminalState(MsgStatusConstant.PENDING)); - assertFalse(MessageRetryQueueServiceImpl.isTerminalState(MsgStatusConstant.RETRYABLE_FAILED)); - } - - @Test - void isTerminalState_everythingElseIsTerminal() { - assertTrue(MessageRetryQueueServiceImpl.isTerminalState(MsgStatusConstant.SUCCESS)); - assertTrue(MessageRetryQueueServiceImpl.isTerminalState(MsgStatusConstant.FAILED)); - assertTrue(MessageRetryQueueServiceImpl.isTerminalState(MsgStatusConstant.FINALFAILED)); - assertTrue(MessageRetryQueueServiceImpl.isTerminalState(MsgStatusConstant.QUOTAEXCEEDED)); - assertTrue(MessageRetryQueueServiceImpl.isTerminalState(MsgStatusConstant.RATE_LIMITED)); - // 白名单默认删:未知/ null 状态视为终态(与 spec「默认删,只保留三个」一致) - assertTrue(MessageRetryQueueServiceImpl.isTerminalState(null)); - } - @Test void calculateNextRetryTime_rateLimitUsesFixed120s() { MessageRetryQueueServiceImpl service = new MessageRetryQueueServiceImpl();