docs(kdoc): 重写信箱生命周期相关 KDoc,改为直白说明并去掉内部编号
原有注释大量引用 §5.1/§5.2/Q2/US-01 这类文档编号和内部简称,跳过了"这段代码在做什么、 为什么这么做",没有读过设计文档的人基本读不懂。本次统一改成先讲清这件事本身、 再说为什么要这样做,编号只在末尾留一处指路。 覆盖本次改动涉及的 24 个 Kotlin 文件(生产 16 个 + 测试 8 个): - 领域与端口:ProcState(补齐全量字段说明与状态/错误分类逐项注释)、 ProcStateRepository / InboxCursorRepository / CminmsgInboxRepository 及 MailboxRow / BackfillDue / Backlog; - 收报:InboxPoller(把"水位连续、遇缺口停下、缺口老化"用大白话讲透)、 InboxService、JdbcCminmsgInboxRepository; - 处理:Pump / MessageProcessor、ScheduleProcessor、DynamicProcessors、 ProcFailure、JdbcProcStateRepository 与游标实现; - 回填与观测:BackfillService、InboxLifecycleHealthIndicator、JobRunner; - 配置与 stub:PipelineProps(三个新增参数说清取值理由)、MailboxProps、 StubRepositories; - 测试:8 个测试类改为"这些用例在守哪几条规矩",并保留 H2 不覆盖 ON CONFLICT 的说明。 术语统一按第一次出现就地解释:水位、处理标记、回填、死信、队头、终态。 纯注释改动;除拆分枚举时按仓库风格补的两个行尾逗号外无代码变更 (已用剥离注释后比对 HEAD 的方式逐文件核对)。测试仍为 78 passed / 1 skipped。
This commit is contained in:
@@ -19,11 +19,12 @@ import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
/**
|
||||
* U07 端到端(stub 装配,等价 /beans 核验):无 MySQL/Redis/Kafka 下,
|
||||
* ①核心 bean 装配齐全;②compat HTTP 写→PG 入队→主泵领取→解码未实装→FAILED(CODEC_ERROR)+退避;
|
||||
* ③U11 重放把 FAILED 拉回 PENDING;④Dispatcher flushSchd 聚合发出 schd。
|
||||
* (生产主路径 JDBC 轮询 InboxPoller;compat HTTP 写路径见 InboxService)。
|
||||
* 后台循环关闭(autostart=false),按需手动 tick,避免测试泄漏线程。
|
||||
* 不接任何外部中间件,用内存实现把整条链跑通:
|
||||
* 核心 bean 能装配、HTTP 写入到进队再到主泵处理、人工重放能把失败消息拉回队列、
|
||||
* 投递按航班聚合并发出去。另外验证死信不会卡住后续消息的发现。
|
||||
*
|
||||
* 生产主路径是 InboxPoller 轮询,HTTP 只是兼容入口。后台循环默认关闭,
|
||||
* 测试里手动 tick,避免留下多余线程。
|
||||
*/
|
||||
@MicronautTest
|
||||
class PipelineSmokeTest {
|
||||
@@ -102,8 +103,8 @@ class PipelineSmokeTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* 回归(message-lifecycle §5.2/§5.3):死信到达终态时同时登记回填意图并立即回填——
|
||||
* 否则永不回填的行会永久占据发现窗口,累积到批大小后收报整体停摆。
|
||||
* 回归用例:死信在进入终态时同时记下回填待办,并马上把标记写回信箱。
|
||||
* 少了这一步,这些行永远占着每批的名额,攒够一批就再也发现不了新消息了。
|
||||
*/
|
||||
@Test
|
||||
fun `dead letter reaches terminal state, gets marked and cannot block later discovery`() {
|
||||
|
||||
@@ -12,8 +12,8 @@ import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
/**
|
||||
* U12:健康指示器 UP 判据为真实 ping(复审 P1 修正)——
|
||||
* bean 缺失 / ping false / ping 抛异常 → DOWN;仅 ping 成功 → UP。
|
||||
* 健康指示器的判定规则:投递端口要靠真实 ping 通过才算 UP,端口缺失、ping 返回 false
|
||||
* 或抛异常都算 DOWN;收报与回填的状态指标按实际数据计算,端口没接上只提示未绑定。
|
||||
*/
|
||||
class HealthIndicatorsTest {
|
||||
|
||||
@@ -39,7 +39,7 @@ class HealthIndicatorsTest {
|
||||
assertEquals(HealthStatus.DOWN, kafkaHealth(null).status) // bean 缺失
|
||||
}
|
||||
|
||||
/** OPS-2(message-lifecycle §5.3):积压、最老未处理信龄、未回填终态与水位滞后。 */
|
||||
/** 检查 /health 里那几个积压指标算得对不对。 */
|
||||
@Test
|
||||
fun `inbox lifecycle reports backlog, oldest age, unmarked terminals and watermark lag`() {
|
||||
val proc = StubProcState()
|
||||
|
||||
+5
-6
@@ -9,12 +9,11 @@ import org.junit.jupiter.api.Test
|
||||
import java.sql.DriverManager
|
||||
|
||||
/**
|
||||
* Flyway 迁移引擎端到端验证(docs/flight-state.md §2 权威模型 + design.md §2.1 +
|
||||
* message-lifecycle.md §5.1/§5.2):
|
||||
* 1. V1 基线 + V2 信箱生命周期迁移在真实 PostgreSQL 上自动成功;
|
||||
* 2. flyway_schema_history 落库且 success = true;
|
||||
* 3. 决策层/管道层/留痕层全表就绪;PIPELINE_LOCK 与 INBOX_CURSOR 单行种子就位;
|
||||
* 4. V2 收敛结果成立:回填事实并入 PROC_STATE,BACKFILL_TODO 下线。
|
||||
* 在真实 PostgreSQL 上跑一遍迁移,确认结果符合预期:
|
||||
* V1 基线加 V2 信箱生命周期都能成功执行、迁移记录显示成功、该建的表和单行种子
|
||||
* (PIPELINE_LOCK、INBOX_CURSOR)都在,回填相关字段进了 PROC_STATE、BACKFILL_TODO 已下线。
|
||||
*
|
||||
* 没有可用的 PostgreSQL 时跳过(不假装通过)。
|
||||
*/
|
||||
class FlywayMigrationTest {
|
||||
|
||||
|
||||
+7
-7
@@ -19,14 +19,14 @@ import java.util.UUID
|
||||
import javax.sql.DataSource
|
||||
|
||||
/**
|
||||
* 信箱生命周期 SQL 语义(message-lifecycle §4/§5.1/§5.2/§11)在真实 JDBC 上的验证。
|
||||
* 以 H2 的 PostgreSQL 兼容模式承载与 V1+V2 等价的表结构——不依赖 docker/外接库,
|
||||
* 覆盖 PG 侧(终态与回填意图同体、到期/超期筛选、积压观测、水位游标)与 MySQL 侧
|
||||
* (区间发现、标记单调)的实际语句行为。
|
||||
* 用真实 JDBC 跑一遍生命周期相关的 SQL,确认语句行为符合预期(不只是接口签名对)。
|
||||
*
|
||||
* 说明:H2 不支持 `INSERT ... ON CONFLICT DO NOTHING`,
|
||||
* [JdbcProcStateRepository.insertIfAbsent] 的入队幂等由 PG 语义与
|
||||
* `InboxPollerTest`(重复轮询不再入队)分别保证。
|
||||
* 库用 H2 的 PostgreSQL 兼容模式,表结构照抄 V1 + V2,因此不需要 docker 或外接数据库
|
||||
* 就能跑。覆盖两边的真实语句:自有 PG 侧(写终态时一并写下回填待办、挑选待回填记录、
|
||||
* 积压统计、水位游标读写)和共享信箱侧(按 ID 区间读、标记只写一次)。
|
||||
*
|
||||
* 有一处覆盖不到:H2 不支持 `INSERT ... ON CONFLICT DO NOTHING`,所以入队幂等没在这里验证,
|
||||
* 由 `InboxPollerTest`(重复轮询不再登记)和 PostgreSQL 本身的语义来保证。
|
||||
*/
|
||||
class InboxLifecycleJdbcSqlTest {
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@ import org.junit.jupiter.api.Test
|
||||
import java.time.Instant
|
||||
|
||||
/**
|
||||
* 收报发现权不变量(docs/message-lifecycle.md §5.1/§5.3 + architecture.md §5 严格 FIFO):
|
||||
* - 扫描按 ID 区间,**不受处理标记影响**:终态而未回填的行不得占据批次、不得阻断新信发现;
|
||||
* - 水位只随成功入队推进,且与入队同事务(中断后由重扫补建);
|
||||
* - 遇空洞即停(较小 ID 未入队时不得被后续消息越过);空洞老化后放行(水位不得永久停摆);
|
||||
* - 收报层不写处理标记。
|
||||
* 收报环节最要紧的几条规矩:
|
||||
* - 取新消息只看 ID,不看处理标记。处理完却没能回填的行(尤其是永远不回填的死信)
|
||||
* 不允许占住批次,也不允许挡住后面的新消息——这是曾经的线上隐患;
|
||||
* - 水位只在成功登记后才推进,而且和登记写在同一个事务里,中断后重扫就能补齐;
|
||||
* - 遇到 ID 缺口先停下来(可能有更小的消息还没到),缺口等太久则跳过(否则水位永远卡住);
|
||||
* - 这一层不碰信箱的处理标记,标记留给回填环节写。
|
||||
*/
|
||||
class InboxPollerTest {
|
||||
|
||||
|
||||
@@ -20,9 +20,12 @@ import java.time.Instant
|
||||
import java.time.ZoneOffset
|
||||
|
||||
/**
|
||||
* 回填通道不变量(docs/message-lifecycle.md §3/§4/§5.2/§11):
|
||||
* 终态即刻补写、失败退避重试、超期期限 R 覆盖退避、标记单调只写空标、
|
||||
* 中间态不适用、回填失败不回改终态、重启后扫描不依赖内存状态。
|
||||
* 回填环节的规矩:
|
||||
* - 处理完马上写标记,写不进去就按退避重试,重启后接着重试(状态都在数据库里);
|
||||
* - 等得太久的消息无视退避强制补写,保证标记最终一定会写上;
|
||||
* - 只写还没有标记的行,已有的值不覆盖;
|
||||
* - 还没处理完的消息(PENDING / FAILED)不许写标记;
|
||||
* - 回填失败只是回填的事,不会把处理结果改回去。
|
||||
*/
|
||||
class BackfillServiceTest {
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ import org.junit.jupiter.api.Test
|
||||
import java.time.LocalDate
|
||||
|
||||
/**
|
||||
* FDEL(docs/flight-state.md §3.3)+ ADFT(§3.3/§2.1)不变量:
|
||||
* ACTIVE→DELETED 发布一次 tombstone 且明细保留;重复/迟到 FDEL 幂等不推进版本;
|
||||
* ADFT 重激活恢复 ACTIVE;新实例建立;缺失标量不误删(§3.3 保守 Set-only)。
|
||||
* 删除与异常航班处理的规矩:删除在用航班时只发一次删除事件、明细保留;
|
||||
* 重复或迟到的删除报文算成功但不推进版本;ADFT 能把删除过的航班重新激活、
|
||||
* 也能新建航班;报文没带的字段不会被清空。
|
||||
*/
|
||||
class FdelAndAdftProcessorTest {
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ import org.junit.jupiter.api.Test
|
||||
import java.time.LocalDate
|
||||
|
||||
/**
|
||||
* 日计划主链路(docs/flight-state.md §3.1/§4)不变量:重放幂等、整包校验失败
|
||||
* DEAD(PROTOCOL)、归属日冲突不落地、DELETED 不恢复且记冲突告警、
|
||||
* 成功路径版本推进 + 事件 + 留痕 + 待办预登记。
|
||||
* 日计划处理的几条规矩:重复消息不重复写数据;整包校验不过就整包不落地;
|
||||
* 航班运营日对不上时整包拒绝;已删除的航班不因为日计划又活过来;
|
||||
* 正常路径要推进版本、发事件、留痕,并把终态和回填待办一起写在同一事务里。
|
||||
*/
|
||||
class ScheduleProcessorTest {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user