fix(P1 follow-ups): 恢复误删 set_runtime_value + 假 DB 适配 P1-K UPSERT

- 恢复 P1-G 编辑时误删的 clear_runtime_value/set_runtime_value
- 修复 bronze 测试 patch 目标(pipeline_write 替代门面 bz.*)
- 增强假 DB:处理 pg_insert(Insert 语句)+ Team name 回退 + League import

全量 319 通过。
This commit is contained in:
shangfangjian
2026-09-22 09:43:48 +08:00
parent eae88f4cd9
commit 5f4075be22
4 changed files with 161 additions and 6 deletions
+53 -2
View File
@@ -72,6 +72,7 @@ class _FakeDB:
RawEvent: list(raw_events),
}
self._teams_by_id: dict[int, Team] = {t.id: t for t in teams if getattr(t, "id", None)}
self._teams_by_name: dict[str, Team] = {t.name: t for t in teams if getattr(t, "id", None)}
self._aliases: dict[str, TeamAlias] = {}
self._next_id = max((t.id for t in teams if getattr(t, "id", None)), default=0)
@@ -86,6 +87,52 @@ class _FakeDB:
return None
async def execute(self, stmt):
# P1-K:LeagueRepository/TeamRepository.get_or_create 使用 pg_insert(Insert 语句,无 column_descriptions)
if not hasattr(stmt, "column_descriptions"):
# 解析 INSERT 值并注册到 _by_entity,使二次查询可命中
try:
values = stmt.compile().params
except Exception:
values = {}
table = getattr(stmt, "table", None)
table_name = getattr(table, "name", None) if table is not None else None
entity_map = {"leagues": League, "teams": Team}
entity = entity_map.get(table_name)
if entity is not None:
obj = entity()
for k, v in values.items():
if k in ("code", "name", "country", "name_zh"):
setattr(obj, k, v)
if getattr(obj, "id", None) is None:
self._next_id += 1
obj.id = self._next_id
if entity not in self._by_entity:
self._by_entity[entity] = []
self._by_entity[entity].append(obj)
if entity is Team:
self._teams_by_id[obj.id] = obj
self._teams_by_name[obj.name] = obj
class _Empty:
def scalar_one_or_none(self_inner):
return None
def scalars(self_inner):
return self_inner
def all(self_inner):
return []
return _Empty()
# P1-K:Team 查询回退到内存映射 name(避免队列/实体分发不完全匹配)
try:
params = stmt.compile().params
except Exception:
params = {}
name_val = next((v for k, v in params.items() if k.startswith("name")), None)
if isinstance(name_val, str) and name_val:
team = self._teams_by_name.get(name_val)
if team:
return _FakeResult([team])
entities = set()
for d in (stmt.column_descriptions or []):
entities.add(d.get("entity") or d.get("type"))
@@ -94,6 +141,10 @@ class _FakeDB:
return _FakeResult(items)
return _FakeResult([])
@staticmethod
def _filter(entity, items, stmt):
return items
async def flush(self):
for obj in self.added:
if getattr(obj, "id", None) is None:
@@ -261,8 +312,8 @@ class TestEventsBronzeIsBestEffort:
raise RuntimeError("infra down")
# Bronze 写入助手直接 import 到 bzzoiro_events 命名空间,需 patch 该处
monkeypatch.setattr(bz_events, "_write_raw_event", _boom)
monkeypatch.setattr(bz_events, "_write_lineage", _boom)
monkeypatch.setattr("src.data.pipeline_write._write_raw_event", _boom)
monkeypatch.setattr("src.data.pipeline_write._write_lineage", _boom)
_patch_fetch(monkeypatch, [_event()])
db = _FakeDB()