feat(processing): 领域/投影/终态三步提交与 FlightProjectionPort(ACM2-79)
PIPELINE_LOCK 跨 Redis 写;MSG_EVENT HELD→PENDING;Redis 失败不终态不投递;V3 迁移。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+12
-8
@@ -60,13 +60,15 @@ msgexchange-v2 怎么处理报文:记录模型、状态机、事务边界、
|
||||
→ FAILED(等待退避重试)
|
||||
→ DEAD(MALFORMED / PROTOCOL / EXHAUSTED,均需人工处置)
|
||||
|
||||
投递:PENDING → SENT
|
||||
→ PENDING(退避后重试)
|
||||
→ DEAD(重试耗尽,记录保留作死信)
|
||||
投递:HELD → PENDING → SENT
|
||||
→ PENDING(退避后重试)
|
||||
→ DEAD(重试耗尽,记录保留作死信)
|
||||
```
|
||||
|
||||
`SUCCEEDED`/`SKIPPED`/`DEAD` 是终态,不挡后续;`FAILED` 仍占队头。用尽重试 → `DEAD(EXHAUSTED)`。错误分类与重放白名单见 [reference.md](reference.md)。
|
||||
|
||||
`HELD` 是尚未放行的待发事件:领域事务登记,投影写成功后由终态事务转 `PENDING`(「事务边界」)。
|
||||
|
||||
## 4. 收报
|
||||
|
||||
### 4.1 收报
|
||||
@@ -116,9 +118,9 @@ processOne(head):
|
||||
载荷缺失 → DEAD(MALFORMED)
|
||||
整包协议拒绝 → DEAD(PROTOCOL),不落半包
|
||||
5. 业务型成功,分三步(INV-3、INV-10):
|
||||
① 事务提交:航班变更 + 待发事件
|
||||
① 事务提交:航班变更 + 待发事件(登记为 HELD,投递领不到)
|
||||
② 写 Redis 航班快照;失败 → 保持未完成,下轮重处理
|
||||
③ 事务提交:SUCCEEDED + 回填意图
|
||||
③ 事务提交:SUCCEEDED + 回填意图 + 待发事件放行(HELD → PENDING)
|
||||
6. 结束:主泵不做回填;回填意图已随终态落库,由扫描补写信箱标记
|
||||
```
|
||||
|
||||
@@ -130,15 +132,17 @@ processOne(head):
|
||||
|---|---|---|---|---|
|
||||
| 收报入队(`insertIfAbsent`) | 是 | 否 | 否 | 同库事务 |
|
||||
| 身份首次绑定 | 否 | 否 | 否 | 单语句 + 唯一约束 |
|
||||
| 业务型领域变更(航班变更 + 待发事件) | 是 | 是 | 是 | 同库事务(`INV-3`) |
|
||||
| 业务型领域变更(航班变更 + 待发事件) | 是 | 是 | 是 | 同库事务(`INV-3`);事件落 `HELD` |
|
||||
| Redis 航班快照写 | 否 | 是(处理步骤锁跨越本步) | 否 | 外部副作用,不在 PG 事务内;写成功是终态事务的前置(`INV-10`) |
|
||||
| 业务型终态(`SUCCEEDED` + 回填意图) | 是 | 是 | 否 | 同库事务(`INV-3`) |
|
||||
| 业务型终态(`SUCCEEDED` + 回填意图 + 事件放行) | 是 | 是 | 否 | 同库事务(`INV-3`) |
|
||||
| 非业务型终态(`MALFORMED` / `PROTOCOL` / `SKIPPED` / `EXHAUSTED`) | 否 | 否 | 否 | 单语句(终态与回填意图同一条 UPDATE) |
|
||||
| 航班历史清理的物理删除 | 是 | 是(落实 `US-14` AC4) | 是 | 同库事务:复查判据 + 历史写入成功后删除 |
|
||||
| 回填(信箱标记 + `BACKFILL_AT`) | 否 | 否 | 否 | 跨库两次单写;幂等可重跑 |
|
||||
| 人工重放(批量改回 `PENDING`) | 否 | 否 | 否 | 单语句批量;`MessageLifecycleGate` 与回填互斥 |
|
||||
|
||||
航班变更与终态不在同一事务,中间夹 Redis 写(`INV-3`、`INV-10`)。`PIPELINE_LOCK` 跨 Redis 写,与历史清理互斥(`US-14` AC4);无第二写者时不额外串行。
|
||||
航班变更与终态不在同一事务,中间夹 Redis 写(`INV-3`、`INV-10`)。三步跑在同一条数据库连接上:进处理步骤先在该连接取会话级咨询锁(`pg_advisory_lock`),两次事务复用这条连接,整步结束才解锁。行锁随提交释放,单靠它盖不住提交之后的 Redis 写,所以第二个写者(历史清理)在自己的事务里也要先取同一把咨询锁,再照旧锁 `PIPELINE_LOCK` 行,两边因此在整段内互斥(`US-14` AC4);无第二写者时不额外串行。
|
||||
|
||||
投影失败时领域事务已提交而终态未写,`MSG_EVENT` 行停在 `HELD`:投递只领 `PENDING`,Kafka 不会先于处理完成发出(`INV-3`)。下一轮重处理按 `MSG_ID` 先清掉上一轮的 `HELD` 行再重新登记,崩溃重启后既不留悬挂行,也不把同一次变更投两遍。
|
||||
|
||||
### 5.4 历史积压
|
||||
|
||||
|
||||
Reference in New Issue
Block a user