YouTube reports a 24/7 stream's archive with the years it has run (prod: 122,962,914 s), and one
such video made the Watch later total read 44,073 hours. A length past a day is now no length
(`Video.length_seconds`, LENGTH_MAX_S): the API sends none, the playlist and channel totals
leave it out and count it as `live_without_length` ("+N live" beside the sum), and the duration
filter, sort and Home budget never match it. Migration 0117 moves the duration sort indexes onto
the length expression. An AST test holds who may still read the raw column.
The migration 0110 test now ends its read before the way down: 0117 builds an index
CONCURRENTLY there, which waited for that open transaction forever.
60 lines
2.2 KiB
Python
60 lines
2.2 KiB
Python
"""Migration 0110's data step, DB-lane: an admin's interval override moves from `scheduler_settings`
|
|
into sysconfig and back, a row for a job that no longer exists is not carried over, and the unread
|
|
SponsorBlock default leaves the store.
|
|
|
|
The schema half is checked by test_migrations.py; a value lost on the way is invisible there.
|
|
"""
|
|
|
|
from alembic import command
|
|
from alembic.config import Config
|
|
from sqlalchemy import text
|
|
|
|
from app import scheduler
|
|
from app.db import engine
|
|
|
|
|
|
def _config(conn) -> dict[str, str]:
|
|
return dict(conn.execute(text("SELECT key, value FROM system_config")).tuples().all())
|
|
|
|
|
|
def test_an_interval_override_moves_into_sysconfig_and_back(db):
|
|
cfg = Config("alembic.ini")
|
|
command.downgrade(cfg, "0109_job_runs")
|
|
try:
|
|
with engine.begin() as conn:
|
|
conn.execute(
|
|
text(
|
|
"INSERT INTO scheduler_settings (job_id, interval_minutes)"
|
|
" VALUES ('rss_poll', 25), ('log_gc', 90), ('retired_job', 5)"
|
|
)
|
|
)
|
|
conn.execute(
|
|
text(
|
|
"INSERT INTO system_config (key, value, encrypted) VALUES"
|
|
" ('sponsorblock_default', 'true', false), ('quota_daily_budget', '5000', false)"
|
|
)
|
|
)
|
|
finally:
|
|
command.upgrade(cfg, "head")
|
|
|
|
with engine.connect() as conn:
|
|
assert _config(conn) == {
|
|
"job_interval_rss_poll": "25",
|
|
"job_interval_log_gc": "90",
|
|
"quota_daily_budget": "5000",
|
|
}
|
|
assert conn.execute(text("SELECT to_regclass('scheduler_settings')")).scalar() is None
|
|
assert scheduler.load_intervals(db)["rss_poll"] == 25
|
|
# The way down rebuilds an index CONCURRENTLY (0117), which waits for every open transaction —
|
|
# the read above left this session's open.
|
|
db.rollback()
|
|
|
|
command.downgrade(cfg, "0109_job_runs")
|
|
try:
|
|
with engine.connect() as conn:
|
|
back = conn.execute(text("SELECT job_id, interval_minutes FROM scheduler_settings"))
|
|
assert dict(back.tuples().all()) == {"rss_poll": 25, "log_gc": 90}
|
|
assert _config(conn) == {"quota_daily_budget": "5000"}
|
|
finally:
|
|
command.upgrade(cfg, "head")
|