YouTube's RSS goes dark per channel for hours (prod 2026-09-18/19: 393 of 396 feeds answered 404 for four hours, sticky per channel, so a retry does not help), and nothing else read a followed channel's new uploads. A channel whose feed has not answered for `rss_fallback_hours` (admin knob, default 2, 0 = off) now gets one page of its uploads playlist through the Data API (1 unit), at most once per window, yielding to the backfill reserve. Spend is attributed to its own quota action.
31 lines
1.0 KiB
Python
31 lines
1.0 KiB
Python
"""add channels.feed_fallback_at — when a channel's uploads were last read through the API because
|
|
its RSS feed would not answer
|
|
|
|
Revision ID: 0088_channels_feed_fallback_at
|
|
Revises: 0087_users_diagnostics_level
|
|
Create Date: 2026-09-19
|
|
|
|
YouTube's RSS feeds go dark for hours at a time, per channel (2026-09-18/19: 393 of 396 answered 404
|
|
for four hours; the same channel answers 404 to every retry). The RSS poll then reads the newest
|
|
uploads through the Data API instead, at a quota cost, and at most once per `rss_fallback_hours` per
|
|
channel: this column is that clock. NULL = never needed it.
|
|
"""
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision: str = "0088_channels_feed_fallback_at"
|
|
down_revision: str | None = "0087_users_diagnostics_level"
|
|
branch_labels: str | None = None
|
|
depends_on: str | None = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.add_column(
|
|
"channels", sa.Column("feed_fallback_at", sa.DateTime(timezone=True), nullable=True)
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_column("channels", "feed_fallback_at")
|