fix(flow): 时间轴两处诚实性缺陷(X1)
① round 号跨重启被复用 ⇒ 时间轴把多个真实轮次并成一块(真机实测 web 的 r:1 挤了 4 路、 startedAt 跨 13:52→21:05)。修法:发号前从落盘播种(MaxRound,json_extract + json_valid 挡坏行), 每会话每进程只播一次、失败只 WARN 且不重试、并发首轮共享一次读;接口形状零变化 ② truncated 一个字段兼两个意思 ⇒ 一页没拉完时前端会说「更早的轮次已过保留期」(假话)。 新增 retentionBoundaryReached(= 保留期启用 且 已翻到底 且 现存最早一轮 round>1 ⇒ 确有轮次被清扫), truncated 语义一字未改;盲区如实登记(整段被清扫会说少、最早一轮落盘失败可能多说) 3 个变异自检(不落账/floor>0/去掉 hasMore 守卫)
This commit is contained in:
1 parent
b36798265a
commit
2bf3b536dd
9 files changed
+820
-12
No files matched your search
@@ -240,6 +240,54 @@ func TestTimeline_EmptyAndNilDB_边界(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestEarlierRoundsSwept_RoundFloorIsTheEvidence_正常 钉住**清扫信号**的判据(切片 X1;
|
||||
// design/19 §7.1):该会话**完整**的轮次列表里,最早一轮的轮次号 > 1 ⇒ 号更小的轮次曾
|
||||
// 发过号且已不在库里 ⇒ 「更早的轮次已被保留期清扫删掉」成立;最早一轮就是 1 ⇒ 没有更早
|
||||
// 的被删,绝不说「已过保留期」。
|
||||
func TestEarlierRoundsSwept_RoundFloorIsTheEvidence_正常(t *testing.T) {
|
||||
t.Parallel()
|
||||
roundsOf := func(rounds ...int) []TimelineRound {
|
||||
out := make([]TimelineRound, 0, len(rounds))
|
||||
for _, r := range rounds {
|
||||
out = append(out, TimelineRound{Key: fmt.Sprintf("r:%d", r), Round: r})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
if EarlierRoundsSwept(roundsOf(1, 2, 3)) {
|
||||
t.Fatal("最早一轮是第 1 轮 ⇒ 没有更早的被清扫,绝不能说「已过保留期」")
|
||||
}
|
||||
if !EarlierRoundsSwept(roundsOf(5, 6)) {
|
||||
t.Fatal("最早一轮是第 5 轮 ⇒ 号更小的轮次确实发过号、已不在库里 ⇒ 必须为 true")
|
||||
}
|
||||
if !EarlierRoundsSwept(roundsOf(3, 7, 12)) {
|
||||
t.Fatal("乱序/跳号不影响判据:取最小轮次号 > 1 即为 true")
|
||||
}
|
||||
// 同一轮的多路(真并行)不改变最早轮次号。
|
||||
parallel := append(roundsOf(2, 3), TimelineRound{Key: "r:2", Round: 2, Lanes: nil})
|
||||
if !EarlierRoundsSwept(parallel) {
|
||||
t.Fatal("同一轮两路时最早的仍是第 2 轮 ⇒ true(多路不该把判据翻成 false)")
|
||||
}
|
||||
}
|
||||
|
||||
// TestEarlierRoundsSwept_UnknownRoundAndEmptyAreConservative_边界 钉住两条保守口径:
|
||||
// 轮次号未知的轮次在场(老行 / 在飞路没有号)时判据**不成立**(返回 false,宁少说不多说),
|
||||
// 空列表同样为 false —— 别把「不知道」说成「被清扫了」。
|
||||
func TestEarlierRoundsSwept_UnknownRoundAndEmptyAreConservative_边界(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if EarlierRoundsSwept(nil) || EarlierRoundsSwept([]TimelineRound{}) {
|
||||
t.Fatal("没有轮次 ⇒ 判据不成立(绝不是「已过保留期」)")
|
||||
}
|
||||
mixed := []TimelineRound{
|
||||
{Key: "t:web-old-1", Round: 0},
|
||||
{Key: "r:5", Round: 5},
|
||||
}
|
||||
if EarlierRoundsSwept(mixed) {
|
||||
t.Fatal("有轮次号未知的轮次在场 ⇒ 号不可信 ⇒ 必须保守为 false")
|
||||
}
|
||||
}
|
||||
|
||||
// roundKeys 取出轮次键序列(断言用)。
|
||||
func roundKeys(rounds []TimelineRound) []string {
|
||||
out := make([]string, 0, len(rounds))
|
||||
|
||||
Reference in new issue
Block a user