From 16974d04f9e76d4244a23a83412b2f2bf9c6e747 Mon Sep 17 00:00:00 2001 From: hongawen <83944980@qq.com> Date: Fri, 19 Jun 2026 17:28:28 +0800 Subject: [PATCH] =?UTF-8?q?fix(retry):=20=E4=BF=AE=E5=A4=8D=20I3=20?= =?UTF-8?q?=E9=99=90=E6=B5=81/=E6=99=AE=E9=80=9A=E5=85=B1=E7=94=A8=20retry?= =?UTF-8?q?Count=20=E8=B7=A8=E6=B1=A1=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 接 cbfee6b。retryCount 原被限流与普通失败共用累加,而终止判定按本次 errorCode 在 12h 兜底与次数上限间翻转:限流重试撑高 retryCount 后一旦 出现普通失败,会被 retryCount>=maxRetry 提前判死;反之普通累计接近上限 后转限流又借 12h 续命绕过次数上限。 最小治本(不动 DB):retryCount 语义收敛为普通失败次数,限流重试冻结 它(靠 firstFailTime+12h 兜底终止)。 - 新增 nextRetryCount(current, rateLimit):限流冻结、普通累加。 - applyRetryUpdate 改用 nextRetryCount;insert 路径首次限流 retryCount=0、 普通=1。firstFailTime 维度本无污染(只设一次),不动。 测试:RetryDecisionLogicTest 新增 2 例锁回归,原 4 例不变,共 6/6 绿; 全模块编译通过。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../retry/MessageRetryQueueServiceImpl.java | 21 +++++++++++++++---- .../service/retry/RetryDecisionLogicTest.java | 21 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) 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 9e371cf..05bc800 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 @@ -75,13 +75,15 @@ public class MessageRetryQueueServiceImpl extends ServiceImpl= existing.getMaxRetry(); @@ -127,6 +130,16 @@ public class MessageRetryQueueServiceImpl extends ServiceImpl= 118 && seconds <= 122, "expected ~120s, got " + seconds); } + + @Test + void nextRetryCount_rateLimitFreezes_normalIncrements() { + // 普通失败:累加,消耗次数预算 + assertEquals(2, MessageRetryQueueServiceImpl.nextRetryCount(1, false)); + // 限流失败:冻结,不消耗次数预算(靠 12h 兜底终止) + assertEquals(1, MessageRetryQueueServiceImpl.nextRetryCount(1, true)); + } + + @Test + void nextRetryCount_rateLimitRetriesDoNotConsumeNormalBudget() { + // I3 回归:首次普通失败后,连续多次限流重试不应吃掉普通失败的次数预算 + int rc = 1; // 首次普通失败入队 + rc = MessageRetryQueueServiceImpl.nextRetryCount(rc, true); // 限流重试 + rc = MessageRetryQueueServiceImpl.nextRetryCount(rc, true); // 限流重试 + rc = MessageRetryQueueServiceImpl.nextRetryCount(rc, true); // 限流重试 + assertEquals(1, rc, "限流重试不应增加普通失败计数"); + rc = MessageRetryQueueServiceImpl.nextRetryCount(rc, false); // 第 2 次普通失败 + assertEquals(2, rc, "普通失败才累加,且计数从未被限流污染"); + } }