feat(scheduler): admin run-now/run-all triggers + live progress + completion notices

Add per-job "Run now" buttons and a "Start all now" button to the admin Scheduler
dashboard (admin-gated endpoints). Triggers run the job in a background thread
independent of its interval, refusing a concurrent run (409). While running, the
long jobs (maintenance, enrich, backfill, shorts) report live progress through a
decoupled contextvar sink, shown as a progress bar on the job row via the existing
4s poll. A manually-triggered run posts a completion notification to the triggering
admin's inbox (scheduled runs stay silent to avoid spam); the inbox renders the
"scheduler" type trilingually from type+data. While here, give the maintenance job
its missing dashboard label/description in all three languages.
This commit is contained in:
npeter83 2026-06-18 04:01:10 +02:00
parent 3a0789ebe7
commit ed4194a8d3
15 changed files with 344 additions and 30 deletions

View file

@ -9,7 +9,7 @@ import logging
from sqlalchemy import select
from sqlalchemy.orm import Session
from app import quota
from app import progress, quota
from app.config import settings
log = logging.getLogger("subfeed.sync")
@ -64,6 +64,7 @@ def run_enrich(db: Session, max_batches: int = 200, floor: int = 200) -> int:
break
n = enrich_pending(db, yt)
total += n
progress.report(total, None, "enrich") # total unknown (drains until empty)
if n == 0:
break
# Revisit transient live/upcoming videos (enrich_pending is one-shot) so an ended
@ -121,6 +122,7 @@ def run_recent_backfill(
try:
videos_added += backfill_channel_recent(db, yt, channel)
processed += 1
progress.report(processed, len(channels), "backfill_recent")
except Exception:
db.rollback()
log.exception("Recent backfill failed for channel %s", channel.id)
@ -166,6 +168,7 @@ def run_deep_backfill(db: Session, max_channels: int = 10, max_pages: int = 5) -
try:
videos_added += backfill_channel_deep(db, yt, channel, max_pages)
processed += 1
progress.report(processed, len(channels), "backfill_deep")
except Exception:
db.rollback()
log.exception("Deep backfill failed for channel %s", channel.id)