From ef99d3038eb0364e792ef9feb0c46fb445427d59 Mon Sep 17 00:00:00 2001 From: windyboy Date: Wed, 23 Sep 2026 17:16:48 +0800 Subject: [PATCH] =?UTF-8?q?docs(acm2-98):=20=E5=91=8A=E8=AD=A6=E5=8F=A3?= =?UTF-8?q?=E5=BE=84=E6=94=B6=E6=95=9B=E5=88=B0=E5=8F=AF=E5=91=8A=E8=AD=A6?= =?UTF-8?q?=E4=BF=A1=E5=8F=B7=EF=BC=8C=E5=A4=96=E9=83=A8=E5=91=8A=E8=AD=A6?= =?UTF-8?q?=E5=BD=92=E9=83=A8=E7=BD=B2=E6=96=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OPS-2 验收改为故障注入验证指标变化;应用侧只保 /metrics 可观察与死信/放弃清单可查,不内置告警通道。 --- docs/architecture.md | 6 +++--- docs/contracts/interface-contract.md | 8 ++++---- docs/implementation.md | 10 +++++----- docs/reference.md | 6 +++--- docs/requirements.md | 8 ++++---- docs/specification.md | 2 +- .../com/gzzn/omms/msgexchange/config/PipelineProps.kt | 4 ++-- .../com/gzzn/omms/msgexchange/delivery/Dispatcher.kt | 2 +- .../com/gzzn/omms/msgexchange/domain/DecodedMessage.kt | 4 ++-- .../infra/health/InboxLifecycleHealthIndicator.kt | 2 +- .../omms/msgexchange/processing/BackfillService.kt | 2 +- .../omms/msgexchange/processing/BackfillServiceTest.kt | 2 +- 12 files changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index ba7d7df..4ca961d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -52,8 +52,8 @@ delivery 投递 jobs 作业:回填 / 出站重试 / 历史清理 / 3. **事务一**:持 `PIPELINE_LOCK`,领域变更、未映射字段记录与待发事件一起提交。 4. **投影**:写 Redis,写成功才算处理完成(`INV-10`);失败保持未完成、下轮重写投影,业务效果幂等(`US-03` AC3)。 5. **事务二**:处理终态与回填意图一起提交。 -6. **回填**:作业把处理标记写回共享信箱(`US-10`);写不上的记录在案并告警。 -7. **投递**:读待发事件发 `KAFKA:msg` / `KAFKA:schd`,至少一次(`C-9`);一直失败的记录保留可查并告警(`US-08`)。 +6. **回填**:作业把处理标记写回共享信箱(`US-10`);写不上的记录在案可查。 +7. **投递**:读待发事件发 `KAFKA:msg` / `KAFKA:schd`,至少一次(`C-9`);一直失败的记录保留可查(`US-08`)。 其余类别与这条主干的差异: @@ -61,7 +61,7 @@ delivery 投递 jobs 作业:回填 / 出站重试 / 历史清理 / |---|---|---|---| | 日计划(`DNLD`/`RESP`) | 第 3 步改为每批一个事务,第 5 步在整包完成后 | 整包成功,含 Redis 刷新(`US-07` AC4/AC5) | 不标记已处理,下轮整包重处理(`US-07` AC4) | | 静态参考数据 | 无第 4 步;一个事务完成落库、终态与回填意图 | 该类落库成功(`US-13` AC1) | 校验不过整类不动,其他类照常(`US-13` AC2) | -| 出站请求 | 不走收报队列:登记新请求并作废同子类型旧请求;`RQRD` 与 `RQFD` 各自最多一条在途,后续请求待前一条结案再写入 `COUTMSGS` | 请求已写入信箱(`US-09` AC1) | `jobs` 按 `REQ_TRACK` 重试仍有效且确认未落信的请求;写入结果不明时记录并告警,不直接重发;交付承诺只到落信(`C-4`) | +| 出站请求 | 不走收报队列:登记新请求并作废同子类型旧请求;`RQRD` 与 `RQFD` 各自最多一条在途,后续请求待前一条结案再写入 `COUTMSGS` | 请求已写入信箱(`US-09` AC1) | `jobs` 按 `REQ_TRACK` 重试仍有效且确认未落信的请求;写入结果不明时记录在案,不直接重发;交付承诺只到落信(`C-4`) | | 航班历史清理(作业) | 不走消息队列:历史写入成功后物理删除 | 实时数据已删(`US-14` AC3) | 历史写不成功不删,下轮重来(`US-14` AC3) | ## 5. 数据归属与一致性 diff --git a/docs/contracts/interface-contract.md b/docs/contracts/interface-contract.md index 54d86ae..e0151d5 100644 --- a/docs/contracts/interface-contract.md +++ b/docs/contracts/interface-contract.md @@ -35,13 +35,13 @@ AODB 经 CIIMS adapter 把 XML 报文写入 `CMINMSGS`,格式以架构指定 | 出站请求 | 本系统只发 `RQRD` 参考数据请求与 `RQFD` 日计划请求,经 `COUTMSGS` 落信,交付承诺止于落信(`US-09`、`C-4`)。 | 超时的时限取值。 | | 在途与作废 | `RQRD` 与 `RQFD` 各自同时最多一条已落信、未结案的请求;同一子类型发新请求时旧请求作废,新请求登记为待发送,等该报文类型的在途请求收到应答、失败或超时后再落信;请求超过时限未等到应答标记超时(`US-09`)。 | 超时的时限取值。 | | 应答匹配 | 应答按报文类型对应到等待中的请求;AODB 发错或迟到的应答不更新数据,记录后跳过(`US-09`);`SCHD-RESP` 只在请求未过期时生效,迟到的应答不更新数据(`US-07`)。 | 请求与应答的对应字段、过期判定的依据字段。 | -| 错误回报 | 收到 `EROR` 时定位到本系统发出的请求,标记失败并告警(`US-09`)。 | `EROR` 与请求的对应字段。 | +| 错误回报 | 收到 `EROR` 时定位到本系统发出的请求,标记失败(`US-09`)。 | `EROR` 与请求的对应字段。 | ## Kafka | 主题 | 已确定的消息语义 | 尚需确定 | |---|---|---| -| `msg` | 单条航班变更通知;Kafka value 是整条 `MSG` 的 JSON(`META` 加对应业务体,空字段不输出),变更与删除由 `META` 的类型与子类型区分(`Q5`);航班动态与删除处理完成后投递;发送失败自动重试,一直失败的记录保留可查并告警(`US-08`);同一 `FLID` 的变更保序,对外按至少一次投递(`CLM-3`,单分区)。删除通知的来源有三处:`FDEL` 删除(`US-06`)、日计划完整名单覆盖范围内缺席删除(`US-07`)、历史清理在物理删除前必要时登记(架构 `D1`)。 | 编码方式(JSON 之外的压缩或封装是否引入)。 | +| `msg` | 单条航班变更通知;Kafka value 是整条 `MSG` 的 JSON(`META` 加对应业务体,空字段不输出),变更与删除由 `META` 的类型与子类型区分(`Q5`);航班动态与删除处理完成后投递;发送失败自动重试,一直失败的记录保留可查(`US-08`);同一 `FLID` 的变更保序,对外按至少一次投递(`CLM-3`,单分区)。删除通知的来源有三处:`FDEL` 删除(`US-06`)、日计划完整名单覆盖范围内缺席删除(`US-07`)、历史清理在物理删除前必要时登记(架构 `D1`)。 | 编码方式(JSON 之外的压缩或封装是否引入)。 | | `schd` | 定时批量发送最新航班状态;待发航班按单批上限聚成 `SCHD.FLTR` 数组 JSON,每批作为单条 record 发出,超限部分后续轮次发出(`C-9`、`Q1`);空字段不输出,字段与类型见 [XSD](../legacy/unisysaodbsis.xsd) 的 `FLTR`;没有变化不发;删除航班不进入本主题,由 `msg` 发一条删除通知;发送失败自动重试,对外按至少一次投递(`US-08`)。 | — | 旧系统线索(来源:旧项目用户故事「前端通知」「动态类(FLOP-*)处理」): @@ -60,8 +60,8 @@ AODB 经 CIIMS adapter 把 XML 报文写入 `CMINMSGS`,格式以架构指定 | 表 | 本系统的操作 | 需要对接方提供的物理契约 | |---|---|---| -| `CMINMSGS` | 按信箱编号升序、分批读取未处理的报文,扫描与回写用同一处理时间列(`CMINMSGS_DATE_PROCESSED`,`Q8`);兼容 HTTP 入口写入 XML 原文;处理完成后写入处理完成时刻,只填空值、不覆盖已有值;写回失败由后台任务重试,一直写不上的记录保留在案并告警(`US-01`、`US-02`、`US-10`)。信箱编号即入库行号,单调递增、不复用、不回退(`Q7`)。 | 表 DDL、信箱编号与报文原文字段、处理时间列的类型与可空性及写入样例(处理标记即该处理时间列,见 [specification.md](../specification.md)「术语」的处理标记;回填只填空值)、状态列 `CMINMSGS_STATUS` 的取值集与写权限(`Q8` 未确认)、写入必需列、原文保留期与清除协议(`C-1`)和索引。 | -| `COUTMSGS` | 写入 `RQRD` 参考数据请求与 `RQFD` 日计划请求;CIIMS adapter 消费。交付承诺止于请求落信;写入结果不明时记录并告警,不直接重发(架构「主流程」)。 | 表 DDL、请求原文字段、写入必需列、编号生成方式、重复落信的识别规则。 | +| `CMINMSGS` | 按信箱编号升序、分批读取未处理的报文,扫描与回写用同一处理时间列(`CMINMSGS_DATE_PROCESSED`,`Q8`);兼容 HTTP 入口写入 XML 原文;处理完成后写入处理完成时刻,只填空值、不覆盖已有值;写回失败由后台任务重试,一直写不上的记录保留在案可查(`US-01`、`US-02`、`US-10`)。信箱编号即入库行号,单调递增、不复用、不回退(`Q7`)。 | 表 DDL、信箱编号与报文原文字段、处理时间列的类型与可空性及写入样例(处理标记即该处理时间列,见 [specification.md](../specification.md)「术语」的处理标记;回填只填空值)、状态列 `CMINMSGS_STATUS` 的取值集与写权限(`Q8` 未确认)、写入必需列、原文保留期与清除协议(`C-1`)和索引。 | +| `COUTMSGS` | 写入 `RQRD` 参考数据请求与 `RQFD` 日计划请求;CIIMS adapter 消费。交付承诺止于请求落信;写入结果不明时记录在案,不直接重发(架构「主流程」)。 | 表 DDL、请求原文字段、写入必需列、编号生成方式、重复落信的识别规则。 | 共享 MySQL 归 CIIMS adapter 方所有;本系统不建表、不改表结构,也不写共享历史表。入站行只写回处理标记,原文保留与清除由库方负责(`C-1`)。外部表的物理字段必须以对接方提供的现行 DDL 与读写样例核对,不能由本文件推造。 diff --git a/docs/implementation.md b/docs/implementation.md index e97f334..24ac012 100644 --- a/docs/implementation.md +++ b/docs/implementation.md @@ -174,8 +174,8 @@ LIMIT PARAM:msgx.pipeline.backfill-batch |---|---|---| | 写入成功 | 标记为空、写入 1 行 | 记 `BACKFILL_AT`,不再重试 | | 早已有标记 | 写入 0 行且信箱行存在 | **视为成功**,不覆盖已有值,记 `BACKFILL_AT` | -| 信箱行不存在 | 写入 0 行且行已删 | 立即放弃(`MISSING_ROW`)并告警 | -| 暂时性故障超 `R` | 超时/连接失败到 `R` 仍未写回 | 停自动重试(`TRANSIENT_DEADLINE`)并告警;`R` 前只退避 | +| 信箱行不存在 | 写入 0 行且行已删 | 立即放弃(`MISSING_ROW`),记入放弃清单与指标供外部告警 | +| 暂时性故障超 `R` | 超时/连接失败到 `R` 仍未写回 | 停自动重试(`TRANSIENT_DEADLINE`),记入放弃清单与指标供外部告警;`R` 前只退避 | 放弃 ≠ 已写回:不写 `BACKFILL_AT`,信箱行不删(`C-1`)。 @@ -184,7 +184,7 @@ LIMIT PARAM:msgx.pipeline.backfill-batch `R` 见 [reference.md](reference.md) `PARAM:msgx.pipeline.overdue-backfill`: - 超 `R` 未写回 → 每轮都试,不等退避。 -- 暂时性故障到 `R` 仍失败 → 停自动重试;`backfill-max-attempts` 只告警。 +- 暂时性故障到 `R` 仍失败 → 停自动重试;`backfill-max-attempts` 只记日志提醒(仍继续重试直到 `R`)。 - `MISSING_ROW` 立即放弃。`R ≤ R_keep`。写回已了结且超保留期(约 1 月,`C-1`)后删原文;放弃行不删。 ## 7. 日计划快照与请求匹配 @@ -212,7 +212,7 @@ PENDING → SENT → DONE - 开放槽:`RQRD`/`RQFD` 各一条(`US-09` AC1);同类新请求前作旧请求过期。 - `COUTMSGS` 确认后才 `SENT`;本地未确认须补偿,不能盲重发。 -- EROR → 标 `FAILED` 并告警(`US-09` AC3)。 +- EROR → 标 `FAILED`(`US-09` AC3),错误定位可查。 - 应答按类型匹配开放请求(`US-09` AC2);时间用本地时钟。 - 参考应答写 `REF_MASTER`;日计划走快照。结案后迟到应答不改状态。 - 出站只保证写入信箱(`C-4`、`CLM-4`)。 @@ -263,7 +263,7 @@ PENDING → SENT → DONE | 领域事务已提交、Redis 写失败或终态未提交 | 该消息无终态(`PENDING`),仍占队头 | 整条消息重处理:Redis 航班快照按当前完整态重写;领域再跑是否只留一次效果见 `US-03`、`G-FLOP-IDEMPOTENT`;已提交结果不回滚(`US-03` AC3) | | 事务已提交、标记未写 | 终态行仍持有回填意图 | 仅补写标记;业务处理结果保持不变 | | 标记写入中途 | 标记仍为空 | 重新写入;重复写入同一值无副作用 | -| 回填时信箱行已不存在 | 写入 0 行且信箱行不存在 | 立即放弃自动重试(`MISSING_ROW`)并告警;放弃不等于标记已确认,仍需人工对账 | +| 回填时信箱行已不存在 | 写入 0 行且信箱行不存在 | 立即放弃自动重试(`MISSING_ROW`)并记入放弃清单;放弃不等于标记已确认,仍需人工对账 | | `RECEIVED_AT` 为 NULL | 超期分支以本地 `ENQUEUED_AT` 判定,不受库方时钟与 NULL 影响 | 按 `R` 超期强补写;未超期则按退避重试 | | 投递目标已接受、`SENT` 未置 | 事件仍 `PENDING` | 允许重发,消费方按事件身份去重 | | PG 从备份恢复 | 终态与事件回退到备份点 | 按至少一次接受重复;不重放业务、不据此改写航班 | diff --git a/docs/reference.md b/docs/reference.md index 36b6d8b..4131fda 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -29,7 +29,7 @@ |---|---|---|---| | `msgx.pipeline.overdue-backfill` | `30d` | 入队后超过期限 `R` 仍未写回处理时间,就立即再试;若仍失败,则停止自动重试。`R` 不得长于信箱行可保证的最短保留期 | 暂定 | | `msgx.pipeline.backfill-batch` | `100` 条 | 一次最多检查多少条待写回信箱的记录 | 暂定 | -| `msgx.pipeline.backfill-max-attempts` | `100` 次 | 失败次数达到此值时告警,仍继续重试直到期限 `R` | 暂定 | +| `msgx.pipeline.backfill-max-attempts` | `100` 次 | 失败次数达到此值时记日志提醒,仍继续重试直到期限 `R` | 暂定 | | `msgx.pipeline.backfill-backoff-ms` | `30000` ms | 首次写回失败后等多久再试 | 暂定 | | `msgx.pipeline.backfill-backoff-cap-ms` | `900000` ms | 以后每次重试最长等多久 | 暂定 | @@ -117,9 +117,9 @@ | `msgx.pipeline.codec.vipf_seen.total` | 收到含 `VIPF` 段的消息数 | 非零:核对 `G-SRVT-VIPF` | | `msgx.pipeline.processing.ignored.total` | 被 `IgnoreRules` 跳过的消息数 | 现行清单仅 `LDM-*`;`REGN`/`RSTA`/`EROR` 已改走 US-13/US-09 | | `msgx.pipeline.delivery.send_failures.total{target}` | 该投递目标累计发送失败次数(进程内,重启归零) | 持续增长且 `dead` 非零:投递链路故障(`OPS-2`) | -| `msgx.pipeline.delivery.dead{target}` | 该投递目标当前死信(`DEAD`)行数 | 非零即告警:死信需人工处置(`OPS-2`;状态语义见 [implementation.md](implementation.md)「状态与错误分类」) | +| `msgx.pipeline.delivery.dead{target}` | 该投递目标当前死信(`DEAD`)行数 | 非零供外部告警:死信需人工处置(`OPS-2`;状态语义见 [implementation.md](implementation.md)「状态与错误分类」) | -未处理消息的统计使用同一份缓存;统计不可用显示 `NaN`,没有记录可比时年龄与编号差显示 `-1`。作业计数在进程重启后归零;作业已启动却连续三个检查周期没有成功运行时,`/health` 报 `DOWN`。 +未处理消息的统计使用同一份缓存;统计不可用显示 `NaN`,没有记录可比时年龄与编号差显示 `-1`。作业计数在进程重启后归零;作业已启动却连续三个检查周期没有成功运行时,`/health` 报 `DOWN`。上表关注信号即告警依据,由部署方配外部告警;应用侧只保证 `/metrics` 可观察与死信/放弃清单可查,不内置告警通道。 ## 模块与代码入口 diff --git a/docs/requirements.md b/docs/requirements.md index f989c03..0954fb7 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -113,7 +113,7 @@ 1. 两个 Kafka 主题:`msg` 发单条航班变更,`schd` 定时批量发最新状态。 2. 发送失败自动重试;同一航班的变更按顺序发送。 -3. 发送一直失败的记录保留并可查,有告警。 +3. 发送一直失败的记录保留并可查。 ### US-09 向 AODB 请求数据 @@ -123,7 +123,7 @@ 1. `RQRD` 与 `RQFD` 各自同时最多一条已落信、未结案的请求;同一子类型发新请求时旧请求作废,新请求待在途请求结案后再落信。请求超过时限未等到应答,标记超时。 2. 应答到达时按报文类型对应到等待中的请求;AODB 发错或迟到的应答不更新数据,记录后跳过。 -3. 收到 EROR(AODB 错误回报):定位到本系统发出的请求,标记失败并告警。 +3. 收到 EROR(AODB 错误回报):定位到本系统发出的请求,标记失败。 ### US-10 回写信箱处理标记 @@ -132,7 +132,7 @@ **验收标准** 1. 处理完成时在本地记录「待标记」,后台任务把它写到 MySQL 信箱。 -2. 写失败自动重试,重启后继续;一直写不上的记录在案并告警。 +2. 写失败自动重试,重启后继续;一直写不上的记录在案可查。 ### US-11 处理记录清理 @@ -185,6 +185,6 @@ | 编号 | 要求 | 验证方式 | |---|---|---| | `OPS-1` | 单实例运行:系统配置不完整时拒绝启动;同一时刻只允许一个实例处理消息。 | 配置错误启动失败测试;双实例同时启动测试。 | -| `OPS-2` | 可观测:消息积压、处理失败、发送失败、标记写回失败都有监控指标和告警。 | 故障注入触发告警;检查监控面板。 | +| `OPS-2` | 可观测:消息积压、处理失败、发送失败、标记写回失败都有监控指标与可告警信号。 | 故障注入验证指标变化;查 `/metrics` 与死信/放弃清单。 | | `OPS-3` | 测试隔离:测试环境的实例使用独立的数据库、Redis、Kafka 主题,不连接生产信箱。 | 配置检查。 | | `OPS-4` | 切换与回退:停旧系统、启新系统完成切换;出问题回退时停新、启旧,未处理的消息由旧系统继续,数据不丢。 | 切换与回退演练记录。 | diff --git a/docs/specification.md b/docs/specification.md index da25814..6504435 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -169,7 +169,7 @@ | C-9、CLM-3 | `US-08` AC1~AC3 | `msg` 单条、`schd` 批量;失败可重试;`msg` 同 `FLID` 保序;同条可能发多次 | | C-10 | `US-13` AC1~AC4 | 全量替换、增删改逐条;空值表示无值不是删除;单类校验失败只停该类 | | INV-1(建立处理记录) | `US-01` AC1/AC2/AC4 | 重扫与重启后记录数不变、行不丢;同一编号重复出现时不新增记录 | -| INV-2 | `US-10` AC1/AC2 | 处理结束后才写回;重启后继续;一直失败有记录与告警 | +| INV-2 | `US-10` AC1/AC2 | 处理结束后才写回;重启后继续;一直失败有记录可查 | | INV-3、INV-10 | `US-03` AC4、`US-05` AC4、`US-06` AC1 | Redis 失败时不记「处理结束」与「还要写回」;完成前不发 Kafka | | INV-4 | `US-07` AC1 | 校验失败后 PG 航班数据不变 | | INV-5 | 架构「数据归属与一致性」 | 航班数据只写入自有 PG | diff --git a/src/main/kotlin/com/gzzn/omms/msgexchange/config/PipelineProps.kt b/src/main/kotlin/com/gzzn/omms/msgexchange/config/PipelineProps.kt index cf4591c..2fface6 100644 --- a/src/main/kotlin/com/gzzn/omms/msgexchange/config/PipelineProps.kt +++ b/src/main/kotlin/com/gzzn/omms/msgexchange/config/PipelineProps.kt @@ -40,8 +40,8 @@ class PipelineProps { var backfillBatch: Int = 100 /** - * 回填的自动重试次数上限。达到上限后**停止自动重试**(置为 abandoned 并告警), - * 但保留人工恢复能力——暂时性故障不该变成永久失去补偿,也不该永久占满扫描批次。 + * 回填单行重试的日志提醒阈值:达到后只记 `warn`,仍继续重试直到期限 `R` 才停。 + * 放弃判据是 `R` 超期,不是次数;真正的告警信号是放弃清单与指标,由部署方配外部告警。 */ var backfillMaxAttempts: Int = 100 diff --git a/src/main/kotlin/com/gzzn/omms/msgexchange/delivery/Dispatcher.kt b/src/main/kotlin/com/gzzn/omms/msgexchange/delivery/Dispatcher.kt index 0b1dd60..846ef82 100644 --- a/src/main/kotlin/com/gzzn/omms/msgexchange/delivery/Dispatcher.kt +++ b/src/main/kotlin/com/gzzn/omms/msgexchange/delivery/Dispatcher.kt @@ -193,7 +193,7 @@ class Dispatcher( /** 一条事件发失败之后怎么走:重试次数加一,到上限就标成 DEAD(EXHAUSTED) 留作死信(次数落库便于追查),否则按退避推到下次再发。 */ private fun retryOrDead(e: MsgEvent, lastError: String) { - counters.sendFailedAdd(e.target) // OPS-2:发送失败按 target 计数,供 /metrics 告警 + counters.sendFailedAdd(e.target) // OPS-2:发送失败按 target 计数,经 /metrics 暴露供外部告警 val eventId = e.eventId ?: return val attempts = e.attempts + 1 if (scheduler.exhausted(attempts)) { diff --git a/src/main/kotlin/com/gzzn/omms/msgexchange/domain/DecodedMessage.kt b/src/main/kotlin/com/gzzn/omms/msgexchange/domain/DecodedMessage.kt index 2bbe7cc..a9adaa8 100644 --- a/src/main/kotlin/com/gzzn/omms/msgexchange/domain/DecodedMessage.kt +++ b/src/main/kotlin/com/gzzn/omms/msgexchange/domain/DecodedMessage.kt @@ -22,12 +22,12 @@ sealed interface MsgKind { /** * 静态参考数据(`implementation.md`「静态参考数据」:`SIS:3.1`~`3.14` 的类别码,3.15 是同类别的 RESP)。 - * 必须走参考数据处理(US-13),不得按"不支持"跳过;处理器落地前保持可重试失败并告警。 + * 必须走参考数据处理(US-13),不得按"不支持"跳过;处理器落地前保持可重试失败并留痕。 */ data class RefData(val type: String) : MsgKind /** - * AODB 错误回报(US-09 AC3):须匹配出站请求并标 FAILED;协调器落地前保持可重试失败并告警。 + * AODB 错误回报(US-09 AC3):须匹配出站请求并标 FAILED;协调器落地前保持可重试失败并留痕。 */ data object Eror : MsgKind diff --git a/src/main/kotlin/com/gzzn/omms/msgexchange/infra/health/InboxLifecycleHealthIndicator.kt b/src/main/kotlin/com/gzzn/omms/msgexchange/infra/health/InboxLifecycleHealthIndicator.kt index 22a83d9..96a84d3 100644 --- a/src/main/kotlin/com/gzzn/omms/msgexchange/infra/health/InboxLifecycleHealthIndicator.kt +++ b/src/main/kotlin/com/gzzn/omms/msgexchange/infra/health/InboxLifecycleHealthIndicator.kt @@ -62,7 +62,7 @@ internal fun lifecycleHealth( snapshot.oldestReceivedAt?.let { Duration.between(it, now).seconds } ?: -1L ), "unmarkedTerminal" to snapshot.unmarkedTerminal, - // 已放弃自动回填的条数:**不等于**标记已完成,需要人工对账;非 0 应告警。 + // 已放弃自动回填的条数:**不等于**标记已完成,需要人工对账;非 0 供外部告警。 "backfillAbandoned" to snapshot.abandonedBackfill, // 最老一条"仍待自动回填"记录的年龄(秒):回填延迟的真实观测值。 "oldestUnmarkedBackfillSeconds" to ( diff --git a/src/main/kotlin/com/gzzn/omms/msgexchange/processing/BackfillService.kt b/src/main/kotlin/com/gzzn/omms/msgexchange/processing/BackfillService.kt index 7af5a3f..1ccc3fa 100644 --- a/src/main/kotlin/com/gzzn/omms/msgexchange/processing/BackfillService.kt +++ b/src/main/kotlin/com/gzzn/omms/msgexchange/processing/BackfillService.kt @@ -24,7 +24,7 @@ import java.time.Instant * * 放弃判据是**时间**(`R` 超期)而不是尝试次数:一次小时级的共享库故障不该把待回填行成批 * 判死、再要求人工成批恢复。`R` 之前只退避重试;到 `R` 仍未打标才停止自动重试并进放弃清单 - * (保留 [reopen] 人工恢复)。`backfill-max-attempts` 因此降级为单行重试的告警阈值。 + * (保留 [reopen] 人工恢复)。`backfill-max-attempts` 只是单行重试的日志提醒阈值(仍继续重试直到 `R`)。 * * 两条底线:回填失败不会把终态改回去,也不会重新执行业务逻辑;写标记只写还是空标记的 * 行,重复执行没有副作用。 diff --git a/src/test/kotlin/com/gzzn/omms/msgexchange/processing/BackfillServiceTest.kt b/src/test/kotlin/com/gzzn/omms/msgexchange/processing/BackfillServiceTest.kt index 0c4a9e7..596c44c 100644 --- a/src/test/kotlin/com/gzzn/omms/msgexchange/processing/BackfillServiceTest.kt +++ b/src/test/kotlin/com/gzzn/omms/msgexchange/processing/BackfillServiceTest.kt @@ -298,7 +298,7 @@ class BackfillServiceTest { /** * 门禁裁决 D1:暂时性故障**不按次数放弃**。即使超过 `backfill-max-attempts` 这个 - * 告警阈值,也继续退避重试——一次小时级的共享库故障不该把待回填行成批判死。 + * 日志提醒阈值,也继续退避重试——一次小时级的共享库故障不该把待回填行成批判死。 */ @Test fun `transient failures keep retrying past the warning threshold`() {