fix(question_gen): raise ValueError on UPDATE of missing rows
record_run_end, update_gates, and update_difficulty now check cursor.rowcount after UPDATE+commit and raise ValueError if 0 rows were affected. Prevents silent telemetry loss. Adds three negative-path tests: - test_record_run_end_missing_run_raises - test_update_gates_missing_item_raises - test_update_difficulty_missing_item_raises Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -212,7 +212,7 @@ class QuestionGenStore:
|
|||||||
批次统计摘要。
|
批次统计摘要。
|
||||||
"""
|
"""
|
||||||
now = datetime.now(tz=UTC).isoformat(timespec="seconds")
|
now = datetime.now(tz=UTC).isoformat(timespec="seconds")
|
||||||
self._conn.execute(
|
cursor = self._conn.execute(
|
||||||
"""
|
"""
|
||||||
UPDATE question_gen_runs
|
UPDATE question_gen_runs
|
||||||
SET ended_at=?, status=?, total_slots=?, accepted=?, rejected=?, heavy_sampled=?
|
SET ended_at=?, status=?, total_slots=?, accepted=?, rejected=?, heavy_sampled=?
|
||||||
@@ -229,6 +229,8 @@ class QuestionGenStore:
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
self._conn.commit()
|
self._conn.commit()
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise ValueError(f"run_id 不存在: {run_id}")
|
||||||
logger.info(
|
logger.info(
|
||||||
"出题批次已结束: run_id={}, status={}, accepted={}/{}",
|
"出题批次已结束: run_id={}, status={}, accepted={}/{}",
|
||||||
run_id,
|
run_id,
|
||||||
@@ -307,7 +309,7 @@ class QuestionGenStore:
|
|||||||
属性,每个属性具有 .verdict.value 和 .reason;以及 passed/reject_reason 属性)。
|
属性,每个属性具有 .verdict.value 和 .reason;以及 passed/reject_reason 属性)。
|
||||||
"""
|
"""
|
||||||
final_status = "accepted" if report.passed else "rejected"
|
final_status = "accepted" if report.passed else "rejected"
|
||||||
self._conn.execute(
|
cursor = self._conn.execute(
|
||||||
"""
|
"""
|
||||||
UPDATE question_gen_items
|
UPDATE question_gen_items
|
||||||
SET gate_key_verify=?, gate_blind_answer=?, gate_multi_true=?,
|
SET gate_key_verify=?, gate_blind_answer=?, gate_multi_true=?,
|
||||||
@@ -325,6 +327,8 @@ class QuestionGenStore:
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
self._conn.commit()
|
self._conn.commit()
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise ValueError(f"item_id 不存在: {item_id}")
|
||||||
|
|
||||||
def update_difficulty(self, item_id: str, difficulty_steps: int) -> None:
|
def update_difficulty(self, item_id: str, difficulty_steps: int) -> None:
|
||||||
"""更新重量抽检产出的 Agent 步数。
|
"""更新重量抽检产出的 Agent 步数。
|
||||||
@@ -336,11 +340,13 @@ class QuestionGenStore:
|
|||||||
difficulty_steps : int
|
difficulty_steps : int
|
||||||
Agent 完成该题所需步数。
|
Agent 完成该题所需步数。
|
||||||
"""
|
"""
|
||||||
self._conn.execute(
|
cursor = self._conn.execute(
|
||||||
"UPDATE question_gen_items SET difficulty_steps=? WHERE item_id=?",
|
"UPDATE question_gen_items SET difficulty_steps=? WHERE item_id=?",
|
||||||
(difficulty_steps, item_id),
|
(difficulty_steps, item_id),
|
||||||
)
|
)
|
||||||
self._conn.commit()
|
self._conn.commit()
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise ValueError(f"item_id 不存在: {item_id}")
|
||||||
|
|
||||||
def get_run_stats(self, run_id: str) -> RunStats:
|
def get_run_stats(self, run_id: str) -> RunStats:
|
||||||
"""查询批次统计摘要。
|
"""查询批次统计摘要。
|
||||||
|
|||||||
@@ -242,3 +242,27 @@ class TestQuestionGenStore:
|
|||||||
"""查询不存在的 run_id 应报错。"""
|
"""查询不存在的 run_id 应报错。"""
|
||||||
with pytest.raises(ValueError, match="run_id"):
|
with pytest.raises(ValueError, match="run_id"):
|
||||||
store.get_run_stats("nonexistent-run")
|
store.get_run_stats("nonexistent-run")
|
||||||
|
|
||||||
|
def test_record_run_end_missing_run_raises(self, store: QuestionGenStore) -> None:
|
||||||
|
"""对不存在的 run_id 调用 record_run_end 应报错。"""
|
||||||
|
stats = RunStats(total_slots=10, accepted=5, rejected=3, heavy_sampled=2)
|
||||||
|
with pytest.raises(ValueError, match="run_id"):
|
||||||
|
store.record_run_end(
|
||||||
|
run_id="ghost-run", status="completed", stats=stats
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_update_gates_missing_item_raises(self, store: QuestionGenStore) -> None:
|
||||||
|
"""对不存在的 item_id 调用 update_gates 应报错。"""
|
||||||
|
report = _MockGateReport(
|
||||||
|
key_verify=_GateResult(_Verdict.PASS, "ok"),
|
||||||
|
blind_answer=_GateResult(_Verdict.PASS, "ok"),
|
||||||
|
multi_true=_GateResult(_Verdict.PASS, "ok"),
|
||||||
|
leak_test=_GateResult(_Verdict.PASS, "ok"),
|
||||||
|
)
|
||||||
|
with pytest.raises(ValueError, match="item_id"):
|
||||||
|
store.update_gates(item_id="ghost-item", report=report)
|
||||||
|
|
||||||
|
def test_update_difficulty_missing_item_raises(self, store: QuestionGenStore) -> None:
|
||||||
|
"""对不存在的 item_id 调用 update_difficulty 应报错。"""
|
||||||
|
with pytest.raises(ValueError, match="item_id"):
|
||||||
|
store.update_difficulty(item_id="ghost-item", difficulty_steps=5)
|
||||||
|
|||||||
Reference in New Issue
Block a user