fix(management): first_reply_fact 同毫秒并列主键冲突+定序抖动——reply_msg_id 进 PK/按(ts,msg_id)排序
评审修正(代码质量评审 Critical#1 + Important#2/#3): - reply_msg_id 进复合 PK(模型+migration b7c8d9e0f1a2 原地改,本地 down/up 重建,表空未部署):同毫秒 F,T,F,T 交换的两个样本 (thread_end_ts, reply_ts) 完全并列不再撞主键(原会中断整个 recompute_all 事务);兼作下钻证据定位回复消息。 - load_conversation 增查 msg_id 并按 (ts, msg_id) 排序, compute_conversation 协议改 3 元组——SQL 等键顺序未定义,原实现 同毫秒 [F,T] 归属随查询抖动(0/1 answered 摇摆)。 - recompute_pairs 每 500 会话显式 flush+进度日志(内存上界对齐 summary.recompute_all 惯例,不再依赖隐式 autoflush)。 - 测试:旧 9 个更新协议;新增同毫秒 F,T,F,T 回归/并列确定性/ 空会话幂等清空,fr_sum 总量断言并入双串测试; test_management_models 构造补新主键列。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,7 @@ async def test_first_reply_fact_roundtrip(make_session):
|
||||
s = make_session
|
||||
s.add(FirstReplyFact(channel="wechat", owner_account_id="wx1", peer_id="p1",
|
||||
thread_end_ts=1_700_000_000_000,
|
||||
reply_ts=1_700_000_600_000,
|
||||
reply_ts=1_700_000_600_000, reply_msg_id="m1",
|
||||
day=20260901, fr_ms=600_000))
|
||||
await s.commit()
|
||||
val = (await s.execute(sa.select(FirstReplyFact.fr_ms))).scalar_one()
|
||||
@@ -31,7 +31,8 @@ async def test_first_reply_fact_roundtrip(make_session):
|
||||
async def test_first_reply_fact_unique_sample(make_session):
|
||||
s = make_session
|
||||
kwargs = {"channel": "wechat", "owner_account_id": "wx1", "peer_id": "p1",
|
||||
"thread_end_ts": 1, "reply_ts": 2, "day": 20260901, "fr_ms": 1}
|
||||
"thread_end_ts": 1, "reply_ts": 2, "reply_msg_id": "m1",
|
||||
"day": 20260901, "fr_ms": 1}
|
||||
s.add(FirstReplyFact(**kwargs))
|
||||
await s.commit()
|
||||
s.add(FirstReplyFact(**kwargs))
|
||||
|
||||
Reference in New Issue
Block a user