Commit Graph
85 Commits
Author SHA1 Message Date
windyboy 43bb561f47 fix(processing): 接通 Redis 投影并修正验证缺口 2026-09-21 17:03:26 +08:00
windyboyandCursor e5449a5cb1 feat(refdata): Q22 basicdata 映射与 ReferenceDataProcessor(ACM2-93)
闭合 Q22;V6 建 basicdata 表组;RefData 走真处理器(DNLD/RESP/ADD/UPD/DEL/RSTA)。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 16:01:06 +08:00
windyboyandCursor 02b0b2f189 feat(flight): UNMAPPED_FIELD、SRVT/VIPF 明细与白名单内未映射留档(ACM2-89/99/100)
V5 迁移;集合段出现才写;白名单 7 类内未落态写入 UNMAPPED_FIELD,不扩白名单。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 15:54:55 +08:00
windyboyandCursor 54b383fa9d feat(outbound): REQ_TRACK/COUTMSGS/schd-sync 与 RESP 守卫(ACM2-92/86)
出站请求状态机与编码;SCHD-RESP 须匹配未过期开放请求;EROR 结案匹配 SENT。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 15:50:14 +08:00
windyboyandCursor b545fd2b58 feat(wave4): GET /all/flights and SCHD day-plan processing (ACM2-80, ACM2-85)
Expose projection read API with MAID filtering and 503 on failure; complete schedule snapshot sweep, field clearing, batched PG via FlightCommit, and contract/PARAM docs with regression tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 15:40:58 +08:00
windyboyandCursor 2c3d6af309 feat(processing): 领域/投影/终态三步提交与 FlightProjectionPort(ACM2-79)
PIPELINE_LOCK 跨 Redis 写;MSG_EVENT HELD→PENDING;Redis 失败不终态不投递;V3 迁移。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 15:24:34 +08:00
windyboyandCursor 891088235c feat(ingress): 按处理时间为空扫描信箱,移除水位消费(ACM2-78)
readUnprocessed 替代 ID 水位;去掉 INBOX_CURSOR/cutover-watermark/max-commit-delay 及相关健康与指标。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 14:49:40 +08:00
windyboyandCursor 23b74ed554 fix(processing): Wave1 — IgnoreRules/ROUT截断/Q9文档/schd FLTR 数组(ACM2-94/88/81/96)
REGN/RSTA/EROR 退出忽略清单;ROUT/ERUT 升序留 4 且不落 SCAT/SCDT;C-1/Q9 统一库方清除;flushSchd 聚合成无 key 的 FLTR 数组。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 14:18:40 +08:00
windyboyandCursor d298fcc48f fix(delivery): claimBatch 排除已暂停 FLID,避免投递饿死(ACM2-95)
同 FLID 事件占满 delivery-batch 时后续轮次不再重复领到同一批;补饥饿回归用例。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 14:11:53 +08:00
windyboyandCursor 2fb9e76919 docs: 纠正对齐后的文档反向漂移(UNSUPPORTED/CHDT/FDEL/Flyway)
ACM2-83/87/90 落地后 reference、implementation、MsgEvent 与迁移注释仍描述旧行为;拆开 UNSUPPORTED 两行,并写清 V1+V2 与删航班只走 msg。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 14:04:55 +08:00
windyboy f9d51399da fix(flight): 历史清理判据对齐 US-14 AC2 五类已结束条件(ACM2-91)
- HistoryRules.isEnded 共享求值器:计划超 3 天/取消超 1h/离港/到港;JDBC 与 stub 同源不漂移
- 删除无依据的 idle/deleted/terminal 三个窗口(reference.md 四行冲突参数重写为 AC2 口径)
- 备降条件依赖 FDIV(DDES/DDIR),落地(Q3、ACM2-100)前显式不命中,参数先行登记
- 修「当日」取系统时钟的缺陷,改由传入 now 推导(测试抓出)
- implementation.md 12.5 与配置、yml 同批对齐
2026-09-21 13:39:18 +08:00
windyboy 1d95926e06 feat(jobs): PROC_STATE 终态行到期清理(ACM2-82)
- 新增 deleteExpiredTerminal:仅删终态 + BACKFILL_AT 非空 + UPDATED_AT 超期的行(US-11)
- ProcStateCleanupJob 每轮 tick 执行,与人工重放共用 MessageLifecycleGate,不持 PIPELINE_LOCK
- 登记参数 msgx.pipeline.terminal-retention(默认 90d,暂定)进 reference.md
- Stub 与 JDBC 实现同口径;补四类候选条件回归
2026-09-21 12:52:26 +08:00
windyboy 477f038cc1 feat(config): 配置值非法无条件拒启,登记启动必需配置清单(ACM2-97)
- 新增 PipelineConfigCheck(@Context):退避档位/播种取值校验不再等 autostart(CLM-7、OPS-1)
- OperationDayZoneCheck 扩展 cutoff-hour 0-23 校验
- reference.md 新增「启动必需配置与显式开关」:必需清单、缺值路径、显式开关与运行时故障的边界
- PipelinePropsBindingTest 补一致退避档位;补非法值/范围用例
2026-09-21 12:46:47 +08:00
windyboy 9bf879ff76 feat(metrics): 投递失败与死信可观测指标,修 flushSchd 首次失败原因丢失(ACM2-98)
- PipelineCounters 按 target 累计发送失败;Dispatcher.retryOrDead 记账(OPS-2)
- 新增 deadByTarget 查询与 DeliveryDeadSnapshotProvider(TTL 缓存),死信存量按 target 暴露
- /metrics 注册 send_failures.total{target} 与 dead{target},登记进 reference.md「指标与健康」
- flushSchd 失败改记真实异常原因,不再退回固定 send-failed
2026-09-21 12:40:53 +08:00
windyboy a1c56f546f fix(delivery): 删除通知只登记 KAFKA:msg,schd 不再发 tombstone(ACM2-87)
- FdelProcessor 移除 schd TOMBSTONE,仅保留 msg 删除通知(C-9)
- HistorySweepJob 补发的清退通知由 schd TOMBSTONE 改为 msg 删除通知
- msg value 形态沿用现状(deleted:true JSON),待 Q5 定稿不改成 null tombstone
- 同步修订 FdelAndAdftProcessorTest / HistorySweepJobTest / HistorySweepPurgePgTest 断言
2026-09-21 12:31:02 +08:00
windyboy df087c7933 fix(delivery): msg 队头失败或退避只暂停同 FLID,不阻塞其他航班(ACM2-95)
- drainKafkaMsg 按分区键维护本轮暂停集:队头失败/退避未到期仅停该 FLID(D2)
- 同一 FLID 内仍严格按 EVENT_ID 保序不越队
- 补三条用例:失败仅停同 FLID、退避未到期仅停同 FLID、同 FLID 跨轮保序(TestClocks 无 sleep)
2026-09-21 12:26:09 +08:00
windyboy 0e09365cf6 fix(codec): CHDT 类字段统一为 SIS 口径 CCLS/CTYP(ACM2-90)
- ChdtXml wire 绑定与 SisWireMapper 映射键改为 CCLS/CTYP(implementation.md「动态运行事件」)
- 新增 V2 迁移将自有 PG FLIGHT_CHUTE 列 chcls/chtyp 更名为 ccls/ctyp,不动已发布的 V1
- FlywayMigrationTest 更新迁移链断言并校验更名后列;补 CHDT 解码→合并往返用例
2026-09-21 12:20:50 +08:00
windyboy 29465e2131 fix(codec): FLOP 子类型白名单,白名单外 STYP 落 Unsupported(ACM2-84)
- kindOf FLOP 分支仅放行现行七类(US-05 AC1),FDEL 独立分派不受影响
- 白名单外子类型(ACTT/CNCL 等 Q3 闭合目标)解码为 Unsupported,经 ACM2-83 路径记 SKIPPED、不改航班
- 补 codec 白名单回归与处理层「跳过且不触碰航班」用例
2026-09-21 11:44:43 +08:00
windyboy 3c577b4d1e fix(processing): 合法不支持类型改记 SKIPPED 终态,参考数据单列 RefData(ACM2-83)
- MsgKind.RefData 承接 SIS:3.1~3.14 类别码,白名单分派对齐 implementation.md
- Unsupported 由 FAILED(UNSUPPORTED) 重试改为 SKIPPED(unsupported) 终态(US-03 AC2)
- RefData 在 ReferenceDataProcessor 实装前保持可重试失败,不被吞为跳过
- 同步更新 IgnoreBranchTest / PipelineSmokeTest 旧断言,补 codec 分派回归
2026-09-21 11:41:34 +08:00
windyboy b4ef787e93 docs(acm2): 重构 spec 并整理 Q 编号
- specification:直白说法、编号一览、合并 Q 台账、补 Q2/Q15
- interface-contract:POST /cminmsgs/send 待确认项指向 Q15
- 代码:SRVT/VIPF 清空语义 Q11 → Q2
2026-09-21 07:54:55 +08:00
windyboy 2bd650a551 docs(acm2-75): 清理空转待决项并对齐全仓旧编号引用
- 删 Q2/Q15/Q19/Q20:时钟偏斜不进判据、实现自定已是结论、原文留存已定、
  运营日冲突处置已由 DEAD(PROTOCOL) 定
- Q6 的 abdg 定案本版不提供;Q22 改为 13 类报文到 admin-api 实体表组的映射
  (REF_MASTER 单表口径退位);Q23 收窄为 SODT+FLID 幂等重试
- C-1 自清口径四方同步(requirements 非目标、US-03 AC2、architecture §6)
- INV-2 吸收回填只写空值;§7 恢复 G-RESP-GUARD
- architecture/implementation/README/V1/oracle/Kotlin/seed 中 40+ 处旧编号
  按映射重指,check-docs 全绿
2026-09-20 07:13:20 +08:00
windyboyandCursor c63d6d4dce docs(acm2-75): 重排 Q 序号并补齐 Redis 投影与查询侧边界
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 13:06:59 +08:00
windyboyandCursor dc1c49af6e docs(acm2-75): 精简不变量与声明边界,去掉无依据条目
审改 specification 管道/航班域/投影与 CLM:作废与需求重复或依据不足的 INV/CLM,白话重写保留条款,并同步架构、实现与引用注释。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 17:26:49 +08:00
windyboyandCursor fd65bb24fb docs(acm2-75): 按需求与架构收口契约和规范
补齐接口契约的入站、Redis 与出站边界,规范对齐已定语义并作废过期条款;Kafka 生产端约束编号改为 D2。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 08:49:19 +08:00
windyboy e57152dd83 docs(acm2-75): 规范全面对齐新需求口径
specification.md 按新需求重写:
- 扫描模型反转:水位/ID 区间 → 处理标记为谓词(C-30 取代 C-1/C-2/C-13;INV-2b 替代 INV-2/4/5)
- Redis 回归为查询投影:处理完成门(INV-23)、投影治理与同源读取(INV-24),INV-11b 扩充非权威清单
- 日计划快照语义反转:缺席航班删除、未携带字段清除(INV-15b),增量报文语义另立(INV-14b)
- 终态记录归档 → 到期删除(INV-25),G-PROC-HST/G-HST-RETENTION/G-REPLAY-CHANNEL/G-FLOP-DIRECTION 关闭并清扫全仓引用
- 重放移出交付范围:R_keep 公式收窄、CLM-3 重定义为重处理幂等、Q6 删除
- 新增 INV-23~28:Redis 完成门、投影治理、清理谓词、参考数据逐类保存/门控、历史先行红线
- C-25/C-26 定案(原子级联不回发 EROR;快照未携带字段清除),Q13/Q14 关闭,Q6/Q12 删除,新增 C-30/C-31

联动:implementation.md 收报/回填/快照/生命周期/FLOP 方向各章按新口径重写;architecture.md
D1/D4 改删除语义;reference.md 退役 archive-after;requirements.md OPS 表改为注册表定义
语法;AGENTS.md 状态边界随新口径更新;check-docs.py OPS 注册表节名同步。

scripts/check-docs.sh 全部通过。
2026-09-14 16:40:00 +08:00
windyboy cedd859bdf docs(acm2-74): consolidate design documentation 2026-09-13 20:31:13 +08:00
windyboy 62f61ad9e4 feat(delivery): 真实 Kafka 投递端口 + 闭合 G-BACKFILL-BACKOFF 配置缺口
- 新增 KafkaDeliveryPort:ProducerRegistry + 同步 Future.get() 至少一次投递,
  闭合 OPS-1 真实适配器要求与 US-07 INV-10/C-29
- 回填退避从硬编码 30s/15min 提升为 backfill-backoff-ms / backfill-backoff-cap-ms
  配置绑定,闭合 [G-BACKFILL-BACKOFF]
- 删除死依赖 micronaut-redis-lettuce(代码零引用,ACM2-28 Redis 已退出阶段 A)
2026-09-13 16:26:03 +08:00
windyboy fc744d0cfd feat(acm2): 闭合 G-KAFKA-D3 / G-IGNORE / G-EVENT-RETENTION 三个缺口
- G-KAFKA-D3:max-in-flight 默认收敛到 1,KafkaD3Check 启动自检钉住三项联合满足 D3
- G-IGNORE:IgnoreRules 在身份绑定后精确匹配 TYPE 字段,命中写 SKIPPED + 回填意图
- G-EVENT-RETENTION:V10 迁移加 SENT_AT 列,投递原子写,EventCleanupJob 有界清理过期 SENT 行
2026-09-13 15:48:16 +08:00
windyboy 17a4bfe91b feat(codec): 观测未落库的 SRVT/VIPF 集合
SRVT/VIPF 只保留在 wire/domain 并计数告警,不落明细表、不参与合并:
出现事实不再被静默丢弃,为 Q13 定案提供真实流量证据([G-SRVT-VIPF])。

- wire DTO:SRVT/SERVICEDATA、VIPF/VIPDATA 与嵌套 VIPT(OPER 为元素属性)
- 出现即留键:缺席与"出现但为空"不再等价;已落库 10 类集合语义不变
- 新增 msgx.pipeline.codec.srvt_seen.total / vipf_seen.total(reference.md 已登记)
- 一并提交此前的 MAFL 文档改动(INV-21/INV-22、flight-state §2.3、G-MAFL 措辞)
2026-09-13 09:21:51 +08:00
windyboy b8738554e6 refactor(ingress): 移除 G1 窗口补偿扫描与迟到到达检测
实际负载不足 10 条/秒,G1 属过度防御。删除迟到到达检测机制、
existingIds 接口、PipelineCounters 字段、lateDetect 配置,
以及文档中 CLM-1/CLM-2 声明与 G1 缺口索引。
2026-09-13 08:08:43 +08:00
windyboy a6b2120836 fix(infra): 消除 StubRepositories 编译警告
- KDoc 移到注解之前(2 处)
- upsertSchd 改显式 null 检查避免 !! 警告
- findBackfillDue 链式调用转 asSequence
- 移除 persistFullState 中 always-null 的 fallback
- markDeleted/revive 改 !! 断言(mains/snapshots 同步写入)
2026-09-12 22:39:16 +08:00
windyboy 799243b0a8 fix(ingress): diagnose missing shared mailbox generated key
共享信箱 insertRaw 取不到 CMINMSGS_ID 时抛出可诊断错误,指明该列必须由库方生成(C-14、Q7);只改适配代码,不动共享 Schema。
2026-09-12 20:56:41 +08:00
windyboy 267eb20219 feat(jobs): expose last job failure time
JobActivity 记录最近失败时刻并进入快照;JobRunner 失败时上报该时刻;新增指标 msgx.pipeline.job.last_failure_age_seconds 与健康明细 lastFailureAgeSeconds(对齐 reference 作业健康口径)。

验证:./gradlew test 145 tests / 0 fail / 0 skipped。
2026-09-12 20:56:41 +08:00
windyboy 8a380c7646 refactor(config): drop system-time defaults from domain and entry points
删除会被误用的系统时间默认值:MsgEvent.createdAt、ProcState.updatedAt、InboxPoller.pollOnce(now)、HistorySweepJob.run(now)、Identity.of(day)。Identity 的日期边界改由 MessageProcessor 按 PARAM:msgx.operation-day.zone 算出后传入(边界关闭时身份值不变);StubProcState/StubInbox 改注入 Clock(测试可传假时钟),全部调用点显式传时间。

验证:./gradlew test 145 tests / 0 fail / 0 skipped。
2026-09-12 20:56:41 +08:00
windyboy ebe81d8665 fix(processing): stamp outbox events from the injected clock
所有生产 MsgEvent 构造点显式传 createdAt:ScheduleProcessor.snapshotEvents、FdelProcessor 删除事件、eventsFor(新增 createdAt 参数,三个调用点传注入时钟)、HistorySweepJob.tombstone(传 run 的 now)。领域默认保留给测试便利,但生产写入不再依赖系统时钟。

验证:./gradlew test 145 tests / 0 fail / 0 skipped。
2026-09-12 20:52:24 +08:00
windyboy 4b71b5bb09 feat(jobs): expose job heartbeat and scan backlog
新增 JobActivity 持有作业心跳与扫描积压,JobRunner 每轮 tick 上报(失败只计数、不刷新心跳),PipelineMetrics 注册 msgx.pipeline.job.heartbeat_age_seconds / ticks.total / failures.total / last_sweep_selected,新增 JobRunnerHealthIndicator(未启动 UP 并标 started=false;已启动但心跳缺失或超过 3×扫描周期 DOWN)。对应 reference 作业健康段与 [G-JOB-HEARTBEAT]。

验证:./gradlew test 145 tests / 0 fail / 0 skipped(新增 JobRunnerTest 2、JobRunnerHealthIndicatorTest 4、PipelineMetrics 指标注册 1)。
2026-09-12 20:52:24 +08:00
windyboy 5beb67dadb fix(ingress): preserve compat receipt semantics
接收结果边界改为 insertRaw 是否返回 ID:接收时间读取失败回退注入 Clock 并留痕,PG insertIfAbsent 失败只记日志与 pgEnqueueFailures 计数,不再冒泡成 HTTP 失败(避免客户端重试多写信箱行)。缺的 PROC_STATE 由收报轮询按 US-01 补建且只建一条(INV-1),入口高 ID 仍等水位追平(INV-4)。

验证:./gradlew test 135 tests / 0 fail / 0 skipped(新增 InboxServiceTest 4 例:读时间失败+入队失败仍返回同一 ID、接收时间 NULL 回退时钟、真实插入失败仍失败且无伪造 ID、轮询对失败入队补建且仅一条)。
2026-09-12 20:43:11 +08:00
windyboy 46e901fd44 fix(jobs): recheck archived flight version before purge
HistorySweepJob 归档成功后进 PIPELINE_LOCK 事务,按 (FLID, STATE_VERSION) 用同一判据复查,仍合格才登记 tombstone 并删除;purgeArchived 改收候选而非裸 FLID 列表,并带 (flid, state_version) 删除守卫。事件与删除同事务提交或回滚(INV-17、INV-18)。

验证:./gradlew test 131 tests / 0 fail(新增「归档后主泵更新同一 FLID → 不删、不发 tombstone」用例)。tombstone 与删除的回滚原子性依赖真实 PG 事务,本机无 Docker 时无法执行。
2026-09-12 20:40:32 +08:00
windyboy d21555091f fix(delivery): upsert latest schedule event
KAFKA:schd 收敛为每 FLID 单行:V9 先按 (STATE_VERSION DESC, EVENT_ID DESC) 收敛存量再建部分唯一索引 uq_schd_event;写入走带谓词的单行 upsert(只进不退、同版本 tombstone 优先、接受新代次即换 EVENT_ID 并重置 PENDING/清旧错误);读取不再 DISTINCT ON;成功确认改按 (EVENT_ID, STATE_VERSION, PENDING) 条件更新,删除 Dispatcher superseded 清理循环。msg 路径不变。

验证:全量 ./gradlew test 129 tests / 0 fail(新增 3 个用例:单行只进不退、同版本 tombstone 不可复活、发送期间新代次保持 PENDING)。V9 的存量收敛/索引与 upsert SQL 需真实 PG,本机无 Docker 时 FlywayMigrationTest 跳过。
2026-09-12 20:38:18 +08:00
windyboy 9554b1aae8 fix(config): fail fast on invalid operation-day zone
运营日时区只认 PARAM:msgx.operation-day.zone:JobRunner、HistorySweepJob、JdbcSnapshotLogRepository.purgeBefore 改走注入的 OperationDayProps;ScheduleProcessor/AdftProcessor 删除「非法值回退字面量」;新增 @Context 启动自检 OperationDayZoneCheck,配置错位在启动时暴露。

验证:./gradlew test 126 tests / 0 fail(新增 OperationDayPropsTest 覆盖合法解析与非法即失败)。
2026-09-12 20:34:56 +08:00
windyboy 3f2a1be75b chore(processing): remove stale backfill comment
BackfillService.attempt 前仍声称「处理完立刻试一次、调用方是主泵」,与类注释及「回填一律扫描驱动」矛盾;删除过时 inline KDoc,保留 @param 说明,运行时代码不变。
2026-09-12 20:32:52 +08:00
windyboy a89755c200 fix(processing): clear replay error state
人工重放把 FAILED/DEAD 拨回 PENDING 时,与 attempts/next_attempt_at 一起清空 error_class 与 last_error,使活动状态不携带上一轮失败结论;identity_key、白名单与 MessageLifecycleGate 不变。

同语句同时改 JDBC 与内存实现,避免两套行为漂移。验证:ReplayServiceTest 3/0、InboxLifecycleJdbcSqlTest 8/0(H2 真实 SQL)。
2026-09-12 20:32:27 +08:00
windyboy eb103d6244 refactor(processing): remove unused processing start field
processing_started_at 没有任何判据消费(终态只看尝试上限),删除字段、仓储接口与方法、主泵写入、重放清理、SELECT/映射与 H2 fixture,并新增 V7 DROP COLUMN;V1–V6 历史迁移不动。

验证:./gradlew test 123 tests / 0 fail;V7 的 DROP 与最终 schema 断言需真实 PG,本机无 Docker 时 FlywayMigrationTest 按既有 assumeTrue 跳过。
2026-09-12 20:31:23 +08:00
windyboy 161914eeb8 fix(processing): keep exhausted failures terminal
ProcFailure.fail 在 markTerminal 后继续执行 update(FAILED),把 DEAD(EXHAUSTED) 覆写回非终态。改为耗尽分支写完终态即返回,保持 INV-6 终态不可逆与 INV-8 回填意图同语句。

回归:ProcFailureTest 覆盖临界次数保持 DEAD、不可回退 FAILED,以及非耗尽退避。
2026-09-12 20:29:23 +08:00
windyboy 817236ca26 fix(processing): 落地 D1/D5/D6 三项裁决,删除 head-deadline 参数
D5(终态判据只保留尝试上限):
- Pump.tick 内联 attempts 判定,删除 head-deadline 相关的毒丸分支与滞留告警代码
- 删除配置项 head-deadline(PipelineProps / application.yml)与 PumpDeadlineTest
- PROCESSING_STARTED_AT 变为只写,注释如实说明当前无判据消费它

D1(回填放弃判据改为时间):
- 暂时性故障在 R 之前只退避重试,不再按尝试次数放弃;到 R 才放弃并记 TRANSIENT_DEADLINE
- backfill-max-attempts 降级为单行重试的告警阈值

D6(超期判据改用本地入队时间):
- 新增 V6 迁移:PROC_STATE 加 ENQUEUED_AT(回填存量后置为非空 + 默认)
- findBackfillDue 的谓词与 overdue 标记改比较 enqueued_at,不再用库方时钟的 received_at
- BackfillDue 增加 overdue;收报与兼容入口显式写入本地入队时间

文档同步:
- 清理 4 处 message-lifecycle.md 章节号死链(Pump/InboxService/PipelineProps/application.yml)
- 关闭 G-HEAD-DEADLINE、G-BACKFILL-ABANDON-BYTIME、G-ENQUEUED-AT 三条缺口登记
- reference/user-stories/README 与实现对齐

验证:./gradlew test ⇒ 122 tests, 0 failures, 1 skipped

Refs: ACM2-45
2026-09-11 20:44:30 +08:00
windyboy a84751bf03 fix(jobs): 留痕清理独立接通历史存储开关;精简死逻辑并对齐陈旧注释 2026-09-11 14:26:44 +08:00
windyboy d909a88167 fix(codec): 解码映射失败产出 CODEC_ERROR,落实退避重试与可重放白名单 2026-09-11 14:25:42 +08:00
windyboy 1e75a81107 fix(pipeline): 修复取报-处理-回填链路的超时、吞吐、回填与 FIFO 问题
外部调用(ACM2-33)
- 共享 MySQL 与自有 PG 全部补有界超时:驱动 connect/socket 超时 + Hikari 池超时
  (注意 Micronaut 的 Hikari 项是毫秒数,不是 Duration 字面量)
- 删除主泵/毒丸路径的 inline 回填:跨库写不再占用 FIFO 关键路径,回填统一由扫描驱动
- 游标自愈:save() 改为「先 UPDATE、缺行 INSERT」,缺行只记一次 ERROR
- Pump/Dispatcher 外层 catch 补 error 日志与失败计数

投递吞吐(ACM2-34)
- Dispatcher 改批量领取;队头退避未到期或首条发送失败即停止本轮(保持目标内保序)
- 有活不再 sleep;删除不可达的 state==SENT 死条件;markSent 移入分支;
  superseded 清理加轮数上限与空 eventId 保护

回填闭环(ACM2-36,V4)
- MISSING(运行时确认行不存在)立即放弃自动重试并告警;暂时性故障达上限后停止自动重试
- 新增 reopen 人工恢复入口;放弃 ≠ 标记已确认(BACKFILL_AT 仍为空,清除前提不成立)
- 扫描改 (BACKFILL_ATTEMPTS, MSG_ID) 公平轮转并排除放弃行,消除全局回填饥饿
- V4 只加字段与必要索引,不按年龄做任何存量推断

切流播种(ACM2-35,V5)
- cutover-watermark 四模式(min/zero/max/显式 ID),默认不播种、代码不做默认选择
- 升级实例拒绝重新播种(SEEDED_AT 为 NULL ≠ 从未消费);播种与水位同语句落库
- 非法取值由启动自检挡下

错误分类与入口契约(ACM2-37)
- 未知 SCHD 子类型改为 UNSUPPORTED,不再静默当全量日计划合并
- ADFT 运营日冲突改走 ProtocolViolation → DEAD(PROTOCOL)
- 兼容入口 receivedAt 缺失回退到注入 Clock;MessageLifecycleGate 强制注入 + 装配断言
- FIFO:主泵只领取 msgId ≤ W,兼容入口登记的行在水位追平前不被领取

时间源与可观测(ACM2-38 / ACM2-41 阶段 0)
- 仓储/处理器/作业全部经注入 Clock;移除 markTerminal/markBackfilled 的 Instant.now() 默认值
- 退避表档位与 max-attempts 对齐并加启动自检
- Micrometer 7 个 gauge(@Context 急切注册)+ /health 与 /metrics 共用积压快照缓存
- 只读迟到检测:监视被放行的空洞 ID 是否后来真的出现,只计数告警、不补入队

Plane: ACM2-33 ACM2-34 ACM2-35 ACM2-36 ACM2-37 ACM2-38 ACM2-41
Tests: 88 → 120(1 skipped 需真实 PG)
2026-09-11 08:08:35 +08:00
windyboy b65728f312 refactor(ingress): 信箱连续上界遍历改用解构
contiguousUpTo 由 row.msgId 改为 for ((msgId, _) in rows);MailboxRow 是 data class,
取值结果相同,行为不变,无配置与迁移影响。

验证:./gradlew test 通过。
2026-09-10 21:03:04 +08:00
windyboy eea11203a2 fix(processing): 收紧消息生命周期与投递约束 2026-09-10 20:39:22 +08:00