feat(content): 自营三平台指标入库管线完善
sync_self_video_metrics 按平台隔离入库与字段口径调整,配套自营指标验收测试 更新。
This commit is contained in:
1 parent
1e9ddffd2f
commit
b0e1b5066d
2 files changed
+193
-72
No files matched your search
@@ -466,6 +466,83 @@ def test_collect_xiaohongshu_rows_from_artifact(tmp_path, monkeypatch):
|
||||
assert row[fields.index("page_metrics")].obj["笔记阅读数"] == "1.2万"
|
||||
|
||||
|
||||
def test_upsert_rows_isolates_single_row_failure():
|
||||
"""单行写入失败只跳过该行,不拖累整批(保存点隔离)。"""
|
||||
import contextlib
|
||||
|
||||
class _Cursor:
|
||||
def fetchone(self):
|
||||
return (1,)
|
||||
|
||||
def __getattr__(self, name):
|
||||
def record(*args, **kwargs):
|
||||
params = args[1] if len(args) > 1 else kwargs.get("params")
|
||||
if params is None or len(params) != len(sync_tool.ROW_FIELDS):
|
||||
return
|
||||
# 模拟毒行: 标题以 POISON 开头的行违反约束
|
||||
title = params[sync_tool.ROW_FIELDS.index("title")]
|
||||
if str(title).startswith("POISON"):
|
||||
raise RuntimeError("value too long")
|
||||
return record
|
||||
|
||||
class _Conn:
|
||||
def __init__(self):
|
||||
self.cursor_stub = _Cursor()
|
||||
self.committed = False
|
||||
|
||||
@contextlib.contextmanager
|
||||
def cursor(self):
|
||||
yield self.cursor_stub
|
||||
|
||||
@contextlib.contextmanager
|
||||
def transaction(self):
|
||||
yield
|
||||
|
||||
def commit(self):
|
||||
self.committed = True
|
||||
|
||||
metric_date = dt.date(2026, 10, 1)
|
||||
rows = [
|
||||
sync_tool.make_row("bilibili", metric_date, "daily.json",
|
||||
account_name="光影行星", video_id="BV1"),
|
||||
sync_tool.make_row("douyin", metric_date, "a.xlsx",
|
||||
account_name="店铺A", video_id="1",
|
||||
title="POISON 这行会失败"),
|
||||
sync_tool.make_row("xiaohongshu", metric_date, "daily.json",
|
||||
account_name="光影行星GYXX旗舰店", video_id="66e"),
|
||||
]
|
||||
conn = _Conn()
|
||||
|
||||
written, failed = sync_tool.upsert_rows(conn, rows)
|
||||
|
||||
assert (written, failed) == (2, 1)
|
||||
assert conn.committed
|
||||
|
||||
|
||||
def test_drop_stale_rows_only_removes_matching_sources():
|
||||
"""陈旧防护按来源文件跳过: 抖音旧导出只清掉抖音行,不拦 B站/小红书。"""
|
||||
stale_excel = Path("chanmama/旧导出_20260823-20260921.xlsx")
|
||||
rows = {
|
||||
("douyin", STORE_FLAGSHIP, "1", dt.date(2026, 10, 1)): sync_tool.make_row(
|
||||
"douyin", dt.date(2026, 10, 1), stale_excel.name, video_id="1"
|
||||
),
|
||||
("bilibili", "光影行星", "BV1", dt.date(2026, 10, 1)): sync_tool.make_row(
|
||||
"bilibili", dt.date(2026, 10, 1), "daily.json", video_id="BV1"
|
||||
),
|
||||
("xiaohongshu", XHS_SHOP, "2", dt.date(2026, 10, 1)): sync_tool.make_row(
|
||||
"xiaohongshu", dt.date(2026, 10, 1), "daily.json", video_id="2"
|
||||
),
|
||||
}
|
||||
|
||||
dropped = sync_tool.drop_stale_rows(rows, [stale_excel])
|
||||
|
||||
assert dropped == 1
|
||||
assert set(rows) == {
|
||||
("bilibili", "光影行星", "BV1", dt.date(2026, 10, 1)),
|
||||
("xiaohongshu", XHS_SHOP, "2", dt.date(2026, 10, 1)),
|
||||
}
|
||||
|
||||
|
||||
def test_douyin_history_backfill_uses_file_mtime_and_filename_account(tmp_path):
|
||||
"""历史回填: 按导出落盘日期各留快照,旧版12列文件按文件名前缀补账号。"""
|
||||
# 旧版 12 列表头(无 达人昵称/抖音号/蝉妈妈链接)
|
||||
|
||||
Reference in new issue
Block a user