Repository navigation
feat(store): 到期提醒改成阶段链(到期前 2 次 + 逾期 2 次),并修掉暂停阶段的认领漏洞 - #40
Merged
Merged
Conversation
对标 #12.5 的两条结论落成代码。 ## 之前 - 到期前只发 **1 次** 提醒(T-7),逾期后 **0 次**,直接进宽限期 → 暂停。 - `expiryStage` 只有 `reminded → suspending` 一条路,`suspendExpired` 只认 `'reminded' | null` 作为可认领前置阶段。 ## 现在 提醒链是一张表(`EXPIRY_REMINDER_STEPS`),每档一次 CAS: null → reminded(T-7) → reminded-final(T-1) → overdue-1(T+1) → overdue-2(T+2) → suspending - **逐档查询**(`listReminderCandidates`)而不是一次捞全再在内存里筛:每档单独限批, 一档积压不会把后面几档饿死;`fromStage` 直接就是 `claimExpiryStage` 的 CAS 条件。 - **漏跑能补**:一次 sweep 可以把落下的几档全部补齐(服务停机两天 → 四档一起发)。 漏发的提醒比迟发的提醒更糟。 - **通知失败只退回上一档**(`resetExpiryStage(id, from, to)`),不是置空 —— 置空会把 第一档提醒重复发给用户。 - **暂停不再卡死**:`suspendExpired` 接受「仍在提醒链上」的任意阶段,否则停在 `overdue-2` 的服务永远不会被暂停(这是旧实现的真 bug,只是旧阶段名少而没暴露)。 ## 为什么不做对方那样的「逾期 3 次」 ZJMF 的 3 次逾期提醒是按它更长的宽限期设计的。我方宽限期固定 3 天,硬塞第 3 次会让 「即将暂停」和「已暂停」在同一轮发出 —— 用户同时收到两条相反信息。所以逾期排 2 档, 第 3 次由「已暂停」通知承担。要改回 3 档加一行常量即可,不需要迁移。 ## 验证 `packages/plugins/store` **203 例全绿**(原 198 + 新增 5): - T-1 发第二档、类型仍是 `service.expiring`; - 逾期第 1/2 天各发一次、类型是 `service.overdue`; - 停机补发:`null` + 已到期 2 天 → 一次 sweep 连推 4 档,终态 `overdue-2`; - 某档通知失败 → 阶段退回上一档(不是 null),恢复后只补这一档; - 停在 `overdue-2` 且过了宽限期的服务仍能被暂停(旧实现会永久卡住)。 `tsc` 干净;`listDueExpiryReminders` 随旧单档逻辑删除(无引用)。
worable233
force-pushed
the
feat/expiry-reminders
branch
from
October 25, 2026 09:05
b539926 to
5d45096
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
对标 #12.5 的两条结论落成代码。
之前
expiryStage只有reminded → suspending一条路,suspendExpired只认'reminded' | null作为可认领前置阶段现在
提醒链是一张表(
EXPIRY_REMINDER_STEPS),每档一次 CAS:listReminderCandidates)而不是一次捞全再在内存里筛:每档单独限批,一档积压不会把后面几档饿死;fromStage直接就是claimExpiryStage的 CAS 条件resetExpiryStage(id, from, to)),不是置空 —— 置空会把第一档提醒重复发给用户suspendExpired接受「仍在提醒链上」的任意阶段,否则停在overdue-2的服务永远不会被暂停(这是旧实现的真 bug,只是旧阶段名少而没暴露)为什么不做对方那样的「逾期 3 次」
ZJMF 的 3 次逾期提醒是按它更长的宽限期设计的。我方宽限期固定 3 天,硬塞第 3 次会让「即将暂停」和「已暂停」在同一轮发出 —— 用户同时收到两条相反信息。所以逾期排 2 档,第 3 次由「已暂停」通知承担。要改回 3 档加一行常量即可,不需要迁移。
验证
packages/plugins/store203 例全绿(原 198 + 新增 5):service.expiringservice.overduenull+ 已到期 2 天 → 一次 sweep 连推 4 档,终态overdue-2overdue-2且过了宽限期的服务仍能被暂停(旧实现会永久卡住)tsc干净;listDueExpiryReminders随旧单档逻辑删除(无引用)。