feat: home growth auto(7→1) and hourly recent-video snapshot
- Add analytics.home_growth_days (auto|1|7); API growth_days=auto tries 7 then 1 - Homepage shows active window and growth-board link; clearer empty reason - New snapshot_recent scheduler task (schedule.recent_snapshot_minutes/days) - run_recent_videos refreshes new aids only; never touches completed/backup - Full 00:01 job keeps ok=1 skip (covers hourly refresh within 1h); mutex with recent
This commit is contained in:
1 parent
04716aec1b
commit
9163f47b76
15 files changed
+496
-22
No files matched your search
@@ -124,7 +124,8 @@ def test_growth_and_cold_start():
|
||||
cold = q.list_videos(sort="growth", growth_days=2)
|
||||
assert cold["available"] is False
|
||||
assert cold["items"] == []
|
||||
assert "两天" in cold["reason"]
|
||||
assert "至少 3 天快照" in cold["reason"]
|
||||
assert cold["growth_days"] == 2
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
@@ -361,10 +362,15 @@ def test_fans_candidates_system_and_export():
|
||||
assert system["errors"] == []
|
||||
assert system["preview"] is False
|
||||
assert system["running"] == {}
|
||||
assert set(system["next_runs"]) >= {"fans", "snapshot", "discover"}
|
||||
assert set(system["next_runs"]) >= {
|
||||
"fans", "snapshot", "discover", "snapshot_recent",
|
||||
}
|
||||
assert system["next_runs"]["snapshot"] > 0
|
||||
assert system["next_runs"]["fans"] > 0
|
||||
assert system["next_runs"]["discover"] > 0
|
||||
assert system["next_runs"]["snapshot_recent"] > 0
|
||||
assert system["schedule"]["recent_snapshot_minutes"] == 60
|
||||
assert system["schedule"]["recent_video_days"] == 2
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
@@ -483,6 +489,7 @@ def test_about_payload():
|
||||
"min_view_for_ranking": 2000,
|
||||
"video_shrink_minutes": 60,
|
||||
"shrink_minutes": None,
|
||||
"home_growth_days": "auto",
|
||||
}
|
||||
assert about["heat_weights"]["view"] == 0.30
|
||||
assert about["followers"]["videos_total"] == 3
|
||||
@@ -553,6 +560,65 @@ def test_stats_query():
|
||||
db.close()
|
||||
|
||||
|
||||
|
||||
def test_growth_auto_falls_back_to_one_day():
|
||||
"""3 天快照撑不起 7 日增长;auto 应降到 1 日。"""
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
db, q = setup(tmp)
|
||||
try:
|
||||
auto = q.list_videos(sort="growth", growth_days="auto", page_size=6)
|
||||
assert auto["available"] is True
|
||||
assert auto["growth_days"] == 1
|
||||
assert {item["aid"] for item in auto["items"]} == {101, 102}
|
||||
first = next(item for item in auto["items"] if item["aid"] == 101)
|
||||
assert first["growth"]["delta"] == 100 # 相邻日
|
||||
|
||||
forced7 = q.list_videos(sort="growth", growth_days=7)
|
||||
assert forced7["available"] is False
|
||||
assert "至少 8 天快照" in forced7["reason"]
|
||||
|
||||
# 配置钉死 7 天:auto 不再降级
|
||||
path = Path(tmp) / "config.json"
|
||||
data = json.loads(path.read_text(encoding="utf-8"))
|
||||
data.setdefault("analytics", {})["home_growth_days"] = 7
|
||||
path.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
|
||||
target = max(path.stat().st_mtime_ns, time.time_ns()) + 1_000_000
|
||||
os.utime(path, ns=(target, target))
|
||||
DASHBOARD_CACHE.clear()
|
||||
pinned = q.list_videos(sort="growth", growth_days="auto")
|
||||
assert pinned["growth_days"] == 7
|
||||
assert pinned["available"] is False
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_snapshot_recent_next_run_follows_completion():
|
||||
import json
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
db, q = setup(tmp)
|
||||
try:
|
||||
repo = Repository(db)
|
||||
finished = FIXED_NOW - 10
|
||||
repo.kv_set(
|
||||
"task:last:snapshot_recent",
|
||||
json.dumps({
|
||||
"name": "snapshot_recent", "ok": True,
|
||||
"started_at": finished - 5, "finished_at": finished,
|
||||
"error": None, "summary": {},
|
||||
}),
|
||||
)
|
||||
DASHBOARD_CACHE.clear()
|
||||
system = q.system()
|
||||
assert system["next_runs"]["snapshot_recent"] == finished + 3600
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def main_test():
|
||||
test_overview()
|
||||
test_video_listing_filters_and_sorting()
|
||||
@@ -568,6 +634,8 @@ def main_test():
|
||||
test_fans_candidates_system_and_export()
|
||||
test_system_status_uses_completed_date_and_running_flags()
|
||||
test_system_next_runs_follow_last_completion_not_wall_clock()
|
||||
test_growth_auto_falls_back_to_one_day()
|
||||
test_snapshot_recent_next_run_follows_completion()
|
||||
print("OK: Web 查询层总览/榜单/详情/UP/时长效率/粉丝/候选/系统/访问统计测试全部通过")
|
||||
|
||||
|
||||
@@ -605,7 +673,9 @@ def test_system_status_uses_completed_date_and_running_flags():
|
||||
system = q.system()
|
||||
assert "snapshot" in system["running"]
|
||||
assert system["running"]["snapshot"]["running"] is True
|
||||
assert set(system["next_runs"]) >= {"fans", "snapshot", "discover"}
|
||||
assert set(system["next_runs"]) >= {
|
||||
"fans", "snapshot", "discover", "snapshot_recent",
|
||||
}
|
||||
|
||||
# 失败记录保留,完成日不变
|
||||
repo.kv_set(
|
||||
|
||||
Reference in new issue
Block a user