feat(processing): 快照流程锁内复核收敛 + 异常显式清除语义 + 语义矩阵定稿 (ACM2-29 P2-5/M3)
- SnapshotFlow 收敛到 v2 §5 事务顺序:锁外仅解析校验;取得 PIPELINE_LOCK 后 锁内复核快照身份(last_message_id 重放短路)→ 锁内读代与当前航班态 → 计算 nextState → 写入 → CAS → 事件 → SUCCEEDED。锁内 CAS 失败属数据异常, 一律回滚 FAILED(INFRA),删除「版本号相同即视为重放」的推断路径(评审 F7/F8 收口) - M3/F4:异常对象(FDIV/FRET/FLAB)显式清除语义——null 字面量/空对象/空串 翻译为 Clear 命令;FlightNextState.clearedKeys 携带本次清除键;增量路径按 映射把前缀标量列置 NULL;库内清除后读视图无该键(线格式保持键缺失,显式 清除表达留待阶段 2 按下游契约定) - StubFlightSchd 增量分支改为 nextState 权威整体替换(引擎已合并当前态), 天然承载 Clear;flattenScalarsOnly 去除冗余循环(L2) - docs/flight-state-semantics.md:16 类结构语义矩阵定稿(P0-A 交付物落库) - 新测试:引擎 0 标记/异常清除/混排 fail-fast 单测;JDBC 异常清除回环用例 验证:MSGX_PG_PORT=5433 真实 PG ./gradlew test --rerun-tasks 105 用例 0 失败 0 跳过
This commit is contained in:
@@ -142,4 +142,40 @@ class FlightStateEngineTest {
|
||||
val next = FlightStateEngine.apply(current, commands, "m2", bumpVersion = true)
|
||||
assertEquals(emptyList<Map<String, String>>(), next.collections["GTDT"])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `exception null payload translates to explicit clear and apply records cleared key`() {
|
||||
val current = FlightNextState(
|
||||
"F1",
|
||||
mapOf("FLNO" to "CA100", "FRET" to """{"REID":"R1","RSN":"diverted"}"""),
|
||||
emptyMap(),
|
||||
3L,
|
||||
"m1",
|
||||
)
|
||||
val commands = FlightStateEngine.commandsFromFields("F1", mapOf("FRET" to "null"), snapshotReplace = false)
|
||||
assertEquals(ScalarCommand.Clear, commands.scalars["FRET"])
|
||||
|
||||
val next = FlightStateEngine.apply(current, commands, "m2", bumpVersion = true)
|
||||
assertFalse(next.scalars.containsKey("FRET"))
|
||||
assertTrue(next.clearedKeys.contains("FRET"))
|
||||
assertEquals("CA100", next.scalars["FLNO"])
|
||||
|
||||
// 非空载荷仍为 Set,且清空后的下一跳 Set 恢复键(clearedKeys 不跨消息携带)
|
||||
val restored = FlightStateEngine.apply(
|
||||
next,
|
||||
FlightStateEngine.commandsFromFields("F1", mapOf("FRET" to """{"REID":"R2"}"""), snapshotReplace = false),
|
||||
"m3",
|
||||
bumpVersion = true,
|
||||
)
|
||||
assertEquals("""{"REID":"R2"}""", restored.scalars["FRET"])
|
||||
assertFalse(restored.clearedKeys.contains("FRET"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `exception clear accepts null literal empty object and empty string`() {
|
||||
for (payload in listOf("null", "{}", "")) {
|
||||
val commands = FlightStateEngine.commandsFromFields("F1", mapOf("FDIV" to payload), snapshotReplace = false)
|
||||
assertEquals(ScalarCommand.Clear, commands.scalars["FDIV"], "payload=[$payload] must be Clear")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user