fix(pbl_evidence): api.py 两条插入路径显式落地主键 gen_pk

- import 区加 from pbl_evidence.pk import gen_pk(与 db/collector 同风格)
- pbl_artifact_create: pick_columns 前 record['id'] = gen_pk('at')(build_insert 路径)
- pbl_evidence_collect: pick_columns 前 record['id'] = gen_pk('ev')(INSERT INTO pbl_evidence 路径)
- 每条插入路径恰好一次 gen_pk,无兜底分支;ON DUPLICATE KEY UPDATE 列集合排除 id,
  避免竞态命中唯一索引时改写已存在行主键
- 响应 QC#3(上次 api 替换为 no-op)/QC#4(直接改源文件)/QC#6(单一落点)

对应 pk.py 自述契约:gen_pk 被 collector/api 每一条插入路径调用。
This commit is contained in:
agent.develop 2026-09-22 22:06:04 +08:00 committed by agent.develop
parent 262e87fc36
commit 57f651fd79

View File

@ -25,6 +25,7 @@ import hashlib
from pbl_common.api import PblError, actor_id, json_dump, now_str, tenant_id
from pbl_evidence.pk import gen_pk
from pbl_evidence.db import (
build_insert, build_where, invalidate_cache, json_loads, pick_columns,
q_all, q_exec, q_one, table_columns,
@ -98,6 +99,7 @@ async def pbl_artifact_create(**kw):
if st:
record['submitted_at'] = st
record['id'] = gen_pk('at')
record = pick_columns(record, cols)
if 'title' not in record:
raise PblError('PBL_E_DB', 'pbl_artifact 缺 title 列,表结构与模型不一致')
@ -273,12 +275,15 @@ async def pbl_evidence_collect(**kw):
'created_at': now_str(),
'updated_at': now_str(),
}
record['id'] = gen_pk('ev')
record = pick_columns(record, cols)
ins_cols = [c for c in record if c in cols]
col_sql = ', '.join('`%s`' % c for c in ins_cols)
val_sql = ', '.join('${%s}$' % c for c in ins_cols)
dup_cols = [c for c in ins_cols if c not in ('tenant_id', 'source_event_id',
'evidence_type', 'dedup_key', 'created_at')]
# 'id' 必须排除:主键在插入前由 pk 模块一次性生成(单一落点),
# 命中唯一索引走 ON DUPLICATE 时不能把已存在行的主键改写成本次新生成的值。
dup_cols = [c for c in ins_cols if c not in ('id', 'tenant_id', 'source_event_id',
'evidence_type', 'dedup_key', 'created_at')]
sql = 'INSERT INTO `pbl_evidence` (%s) VALUES (%s)' % (col_sql, val_sql)
if dup_cols:
sql += ' ON DUPLICATE KEY UPDATE ' + ', '.join('`%s`=VALUES(`%s`)' % (c, c) for c in dup_cols)