feat(maintenance): scheduled job to retire unplayable videos
Add a daily maintenance/validation job that detects videos which can't be played anywhere and retires them safely. Two phases: re-check already-flagged videos (recover if available again, else hard-delete once the grace period elapses, cascading to states/playlist items), and a rolling re-validation of the least-recently-checked currently-available videos that flags newly-unplayable ones (hidden from the feed immediately via unavailable_since). Detection is ~free: a video missing from the videos.list response is deleted-or-private; an `upcoming` premiere >2 days past its scheduled start that never went live is abandoned. A still-live broadcast is kept (legit 24/7 stream). Enrichment now also fetches part=status to populate the status columns. Grace is 7 days for removed videos, none for abandoned. Before deleting, affected users get one batched notification (never per-video). Interval is admin-tunable via the Scheduler dashboard; batch size and grace are config. Quota-attributed to the system and bounded by the same backfill reserve as the other jobs.
This commit is contained in:
parent
3ae42409b3
commit
05df599f7a
6 changed files with 280 additions and 1 deletions
|
|
@ -217,6 +217,7 @@ def apply_video_details(video: Video, item: dict) -> None:
|
|||
stats = item.get("statistics", {})
|
||||
topics = item.get("topicDetails", {})
|
||||
live = item.get("liveStreamingDetails")
|
||||
status = item.get("status", {})
|
||||
|
||||
video.title = snippet.get("title") or video.title
|
||||
video.description = snippet.get("description")
|
||||
|
|
@ -232,6 +233,11 @@ def apply_video_details(video: Video, item: dict) -> None:
|
|||
"defaultAudioLanguage"
|
||||
)
|
||||
video.live_status = _live_status(snippet, live)
|
||||
# status part: used by the maintenance/validation job to judge playability.
|
||||
if status:
|
||||
video.embeddable = status.get("embeddable")
|
||||
video.privacy_status = status.get("privacyStatus")
|
||||
video.upload_status = status.get("uploadStatus")
|
||||
# is_short is decided separately by the youtube.com/shorts probe (run_shorts_classification).
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue