fix: close data integrity and hot-reload review findings
Backfill same-day snapshots for newly added or restored videos, preserve successful fan snapshots on resume, persist incomplete state before forced re-runs, and split collection completion from backup completion so failed backups can retry without API calls. Reject missing data payloads instead of treating them as empty folders, guard against mass-unfav on suspicious empty remote folders, rebuild Bilibili clients when credentials change, recompute primary folder ownership from active relations with per-folder fav_time, preserve original titles for dropped invalid videos, poll config every 60 seconds, and fix favsort verify interval and mixed resource types.
This commit is contained in:
1 parent
178ab64b18
commit
6a21b5d905
21 files changed
+895
-82
No files matched your search
@@ -18,7 +18,7 @@ F1 = FolderConfig(year=2025, media_id=4451053851, title="2025")
|
||||
F2 = FolderConfig(year=2026, media_id=3700023351, title="2026")
|
||||
|
||||
|
||||
def resource(aid, *, attr=0, up_mid=100, title="视频", bvid=None):
|
||||
def resource(aid, *, attr=0, up_mid=100, title="视频", bvid=None, fav_time=None):
|
||||
return FavResource(
|
||||
aid=aid,
|
||||
bvid=bvid or f"BV{aid}",
|
||||
@@ -29,7 +29,7 @@ def resource(aid, *, attr=0, up_mid=100, title="视频", bvid=None):
|
||||
duration=600,
|
||||
cover="http://example/cover.jpg",
|
||||
attr=attr,
|
||||
fav_time=None,
|
||||
fav_time=fav_time,
|
||||
)
|
||||
|
||||
|
||||
@@ -227,6 +227,72 @@ def test_folder_sync_metadata_and_counts():
|
||||
db.close()
|
||||
|
||||
|
||||
def test_primary_folder_is_order_independent():
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
db, repo = setup(tmp)
|
||||
try:
|
||||
repo.upsert_from_fav(resource(1, fav_time=100), F1.media_id, was_added=True)
|
||||
assert repo.get_video(1)["folder_id"] == F1.media_id
|
||||
repo.upsert_from_fav(resource(1, fav_time=200), F2.media_id, was_added=True)
|
||||
assert repo.get_video(1)["folder_id"] == F2.media_id
|
||||
|
||||
# 全量刷新按相反顺序遍历,主归属仍应指向 fav_time 更新的夹
|
||||
repo.upsert_from_fav(resource(1, fav_time=100), F1.media_id, was_added=False)
|
||||
assert repo.get_video(1)["folder_id"] == F2.media_id
|
||||
repo.upsert_from_fav(resource(1, fav_time=200), F2.media_id, was_added=False)
|
||||
assert repo.get_video(1)["folder_id"] == F2.media_id
|
||||
|
||||
# 从主夹移除、另一个夹仍持有时,主归属切换
|
||||
status = repo.mark_resource_removed(F2.media_id, 1)
|
||||
assert status == "active"
|
||||
assert repo.get_video(1)["folder_id"] == F1.media_id
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_dropped_invalid_preserves_original_title():
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
db, repo = setup(tmp)
|
||||
try:
|
||||
repo.upsert_from_fav(
|
||||
resource(1, title="原始标题"), F1.media_id, was_added=True
|
||||
)
|
||||
repo.set_video_status(1, "dropped")
|
||||
repo.upsert_from_fav(
|
||||
resource(1, title="已失效视频", attr=9),
|
||||
F1.media_id,
|
||||
was_added=False,
|
||||
)
|
||||
video = repo.get_video(1)
|
||||
assert video["status"] == "dropped"
|
||||
assert video["title"] == "原始标题"
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_pending_snapshot_aids():
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
db, repo = setup(tmp)
|
||||
try:
|
||||
repo.upsert_from_fav(resource(1), F1.media_id, was_added=True)
|
||||
repo.upsert_from_fav(resource(2), F1.media_id, was_added=True)
|
||||
repo.upsert_from_fav(resource(3), F1.media_id, was_added=True)
|
||||
repo.set_video_status(3, "unfaved")
|
||||
repo.upsert_snapshot(
|
||||
"2026-10-31", 1,
|
||||
metrics={"view": 1, "like": 1, "favorite": 1, "coin": 1,
|
||||
"share": 1, "reply": 1, "danmaku": 1},
|
||||
ok=True, err=None, captured_at=1,
|
||||
)
|
||||
repo.upsert_snapshot(
|
||||
"2026-10-31", 2,
|
||||
metrics=None, ok=False, err="x", captured_at=1,
|
||||
)
|
||||
assert repo.pending_snapshot_aids("2026-10-31") == [2, 3]
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def main():
|
||||
test_upsert_and_folder_resource()
|
||||
test_invalid_attr_and_missing()
|
||||
@@ -236,6 +302,9 @@ def main():
|
||||
test_multi_folder_moves_primary_and_warns()
|
||||
test_blacklist_seed_idempotent()
|
||||
test_folder_sync_metadata_and_counts()
|
||||
test_primary_folder_is_order_independent()
|
||||
test_dropped_invalid_preserves_original_title()
|
||||
test_pending_snapshot_aids()
|
||||
print("OK: 收藏夹/视频状态机与黑名单测试全部通过")
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user