feat(scheduler): each row shows its last three runs, an interrupted run as such, and the ad-hoc runs beside the jobs
A row's one dot said how the LAST run went, and an interrupted run fell through to "idle" — a grey dot that read as "no run recorded". The row now leads with its last three runs, newest first, each named for a screen reader and in its tooltip (how it went, when, who started it); an interrupted run is a ring, set apart from a skipped run and a failure, and its line says the server restarted under it. A channel's full-history backfill gets its own "Ad-hoc runs" block: its runs, its channel and what it fetched, no interval and no run button — it needs its target. AD_HOC_JOBS names every such job; the backend-id contract holds their names in both languages, and run_ad_hoc refuses any other id.
This commit is contained in:
@@ -13,7 +13,7 @@ import pytest
|
||||
from sqlalchemy import select
|
||||
|
||||
from app import jobruns, logs, logsink, quota, scheduler, state
|
||||
from app.models import AuditLog, JobRun, Notification, QuotaEvent
|
||||
from app.models import AuditLog, Channel, JobRun, Notification, QuotaEvent
|
||||
from app.runstatus import RunStatus, RunTrigger
|
||||
|
||||
_JOB = "unit_test_claim" # not a real job id — exercises the primitive without touching live jobs
|
||||
@@ -335,10 +335,43 @@ def test_an_ad_hoc_run_is_the_users_run_of_its_target_with_its_spend_and_failure
|
||||
assert (failed.status, failed.error) == ("error", "quota exceeded")
|
||||
|
||||
|
||||
def test_the_page_shows_the_ad_hoc_runs_beside_the_jobs_with_their_channel(db, make_user):
|
||||
user = make_user("shown@example.com")
|
||||
db.add(Channel(id="UC_shown", title="BBC Earth"))
|
||||
db.commit()
|
||||
scheduler._ad_hoc("channel_backfill", lambda: {"skipped": "at capacity"}, user.id, "UC_none")
|
||||
scheduler._ad_hoc("channel_backfill", lambda: {"videos_added": 69}, user.id, "UC_shown")
|
||||
|
||||
(row,) = scheduler.scheduler_snapshot(db)["ad_hoc"]
|
||||
assert (row["id"], row["running"], row["target"], row["target_title"]) == (
|
||||
"channel_backfill",
|
||||
False,
|
||||
"UC_shown",
|
||||
"BBC Earth",
|
||||
)
|
||||
assert (row["status"], row["result"], row["last_trigger"]) == (
|
||||
"ok",
|
||||
{"videos_added": 69},
|
||||
"ad_hoc",
|
||||
)
|
||||
assert len(row["recent"]) == 2
|
||||
assert all(j["id"] != "channel_backfill" for j in scheduler.scheduler_snapshot(db)["jobs"])
|
||||
|
||||
jobruns.start("channel_backfill", RunTrigger.AD_HOC, user.id, "UC_shown")
|
||||
assert scheduler.scheduler_snapshot(db)["ad_hoc"][0]["running"] is True
|
||||
|
||||
|
||||
def _finished(db, job) -> list[JobRun]:
|
||||
return [r for r in _runs(db, job) if r.status != "running"]
|
||||
|
||||
|
||||
def test_an_ad_hoc_job_outside_the_named_list_is_refused(live_scheduler):
|
||||
"""The page names every ad-hoc job from AD_HOC_JOBS; one outside it would show as a bare id."""
|
||||
with pytest.raises(KeyError):
|
||||
scheduler.run_ad_hoc("unnamed_job", dict, actor_id=1, target="x")
|
||||
assert live_scheduler.get_jobs() == []
|
||||
|
||||
|
||||
def test_a_second_ad_hoc_request_before_the_first_starts_is_that_same_run(
|
||||
db, make_user, live_scheduler
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user