feat(config): job intervals live in sysconfig, every setting says when it applies, the unread SponsorBlock default goes
An interval override was a row of its own table beside the one store every other admin knob uses; it is now the `job_interval_<job>` sysconfig key (migration 0110 copies them over and drops the table). The Scheduler page stays its one editor: the Configuration page and the setup wizard neither list nor write those keys, since a write there would skip the reschedule. Each ConfigSpec now states `applies` (required, no default). Every key is `live`, held by a scan that finds no read at import time; a `restart` key is refused until the page can say so. A second scan requires a reader for every key on the Configuration page — `sponsorblock_default` had none since it was added, so it leaves the registry, the translations and the store.
This commit is contained in:
@@ -10,7 +10,7 @@ import { vocabKey } from "../lib/vocab";
|
||||
// the registries straight from the backend sources:
|
||||
// - `sysconfig.SPECS` → `config.groups.<group>`, `config.fields.<key>.label` + `.hint`, and for a
|
||||
// "choice" key `config.choices.<key>.<option>` — the options read from its Literal in config.py
|
||||
// - `scheduler.JOB_INTERVALS` and `scheduler.AD_HOC_JOBS` → `scheduler.jobs.<id>` + `scheduler.jobDesc.<id>`
|
||||
// - `sysconfig.JOB_INTERVAL_DEFAULTS` and `scheduler.AD_HOC_JOBS` → `scheduler.jobs.<id>` + `scheduler.jobDesc.<id>`
|
||||
// - the `audit` action enum → `auditActions.<id>`; the `quota` action enum → `quotaActions.<id>`
|
||||
// and the other way round: a name left behind for an id the backend dropped is dead weight that reads
|
||||
// as a live setting to the next person (`plex_sync_interval_min` moved to the scheduler long ago).
|
||||
@@ -57,12 +57,13 @@ const choiceIds = specs
|
||||
.filter((s) => s.type === "choice")
|
||||
.flatMap((s) => choicesOf(s.attr).map((c) => `config.choices.${s.key}.${c}`));
|
||||
const schedulerPy = backend("scheduler.py");
|
||||
// The interval jobs, and the ad-hoc ones (`AD_HOC_JOBS`, a tuple of constants named beside it).
|
||||
// The interval jobs (sysconfig's `JOB_INTERVAL_DEFAULTS`: job → its default's setting), and the
|
||||
// ad-hoc ones (`AD_HOC_JOBS` in scheduler.py, a tuple of constants named beside it).
|
||||
const jobs = [
|
||||
...[
|
||||
...(schedulerPy.split("JOB_INTERVALS")[1] ?? "")
|
||||
...(backend("sysconfig.py").split("JOB_INTERVAL_DEFAULTS: dict[str, str] = {")[1] ?? "")
|
||||
.split("}")[0]!
|
||||
.matchAll(/"(\w+)": settings\./g),
|
||||
.matchAll(/"(\w+)": "\w+",/g),
|
||||
].map((m) => m[1]!),
|
||||
...[...(/^AD_HOC_JOBS = \(([^)]*)\)/m.exec(schedulerPy)?.[1] ?? "").matchAll(/\b[A-Z_]+\b/g)].map(
|
||||
(m) => new RegExp(`^${m[0]} = "(\\w+)"$`, "m").exec(schedulerPy)?.[1] ?? m[0],
|
||||
|
||||
@@ -162,10 +162,6 @@
|
||||
"label": "Worker concurrency",
|
||||
"hint": "How many downloads the worker processes in parallel."
|
||||
},
|
||||
"sponsorblock_default": {
|
||||
"label": "SponsorBlock by default",
|
||||
"hint": "Enable SponsorBlock (skip sponsor segments) for newly created custom download profiles."
|
||||
},
|
||||
"audit_retention_days": {
|
||||
"label": "Retention (days)",
|
||||
"hint": "How long admin audit-log entries are kept before the audit-log cleanup job prunes them. 0 = keep forever. Default 180."
|
||||
|
||||
@@ -162,10 +162,6 @@
|
||||
"label": "Párhuzamos letöltések",
|
||||
"hint": "Hány letöltést dolgoz fel egyszerre a letöltő folyamat."
|
||||
},
|
||||
"sponsorblock_default": {
|
||||
"label": "SponsorBlock alapból",
|
||||
"hint": "SponsorBlock (szponzorszakaszok átugrása) bekapcsolása az újonnan létrehozott egyéni letöltési profilokhoz."
|
||||
},
|
||||
"audit_retention_days": {
|
||||
"label": "Megőrzés (nap)",
|
||||
"hint": "Meddig maradnak meg az admin-naplóbejegyzések, mielőtt az eseménynapló-takarító feladat törli őket. 0 = örökre. Alapérték 180."
|
||||
|
||||
Reference in New Issue
Block a user