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:
浅念
2026-09-09 13:18:08 +08:00
parent 0b0dd0808b
commit 58d274096d
5 changed files with 129 additions and 30 deletions
@@ -26,6 +26,9 @@ _TABLES = [
sa.Column("peer_id", sa.String(length=128), primary_key=True),
sa.Column("thread_end_ts", sa.BigInteger(), primary_key=True),
sa.Column("reply_ts", sa.BigInteger(), primary_key=True),
# 同毫秒 F,T,F,T 交换的 (thread_end_ts, reply_ts) 并列去重(一条回复
# 恰好闭合一个串,reply_msg_id 唯一定位);兼作下钻证据定位回复消息
sa.Column("reply_msg_id", sa.String(length=64), primary_key=True),
sa.Column("day", sa.Integer(), nullable=False),
sa.Column("fr_ms", sa.BigInteger(), nullable=False),
)),