split scheduling into scan + process windows, move controls to settings page
Build and Push Docker Image / build (push) Failing after 8s
Build and Push Docker Image / build (push) Failing after 8s
the old one-window scheduler gated only the job queue. now the scan loop and the processing queue have independent windows — useful when the container runs as an always-on service and we only want to hammer jellyfin + ffmpeg at night. config keys renamed from schedule_* to scan_schedule_* / process_schedule_*, plus the existing job_sleep_seconds. scheduler.ts exposes parallel helpers (isInScanWindow / isInProcessWindow, waitForScanWindow / waitForProcessWindow) so each caller picks its window without cross-contamination. scan.ts checks the scan window between items and emits paused/resumed sse. execute.ts keeps its per-job pause + sleep-between-jobs but now on the process window. /api/execute/scheduler moved to /api/settings/schedule. frontend: ScheduleControls popup deleted from the pipeline header, replaced with a plain Start queue button. settings page grows a Schedule section with both windows and the job sleep input. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+16
-24
@@ -8,13 +8,12 @@ import { getItem, refreshItem } from "../services/jellyfin";
|
||||
import { loadLibrary as loadRadarrLibrary, isUsable as radarrUsable } from "../services/radarr";
|
||||
import { upsertJellyfinItem } from "../services/rescan";
|
||||
import {
|
||||
getSchedulerState,
|
||||
isInScheduleWindow,
|
||||
msUntilWindow,
|
||||
nextWindowTime,
|
||||
getScheduleConfig,
|
||||
isInProcessWindow,
|
||||
msUntilProcessWindow,
|
||||
nextProcessWindowTime,
|
||||
sleepBetweenJobs,
|
||||
updateSchedulerState,
|
||||
waitForWindow,
|
||||
waitForProcessWindow,
|
||||
} from "../services/scheduler";
|
||||
import { loadLibrary as loadSonarrLibrary, isUsable as sonarrUsable } from "../services/sonarr";
|
||||
import type { Job, MediaItem, MediaStream } from "../types";
|
||||
@@ -105,17 +104,20 @@ async function runSequential(jobs: Job[]): Promise<void> {
|
||||
try {
|
||||
let first = true;
|
||||
for (const job of jobs) {
|
||||
// Pause outside the scheduler window
|
||||
if (!isInScheduleWindow()) {
|
||||
emitQueueStatus("paused", { until: nextWindowTime(), seconds: Math.round(msUntilWindow() / 1000) });
|
||||
await waitForWindow();
|
||||
// Pause outside the processing window
|
||||
if (!isInProcessWindow()) {
|
||||
emitQueueStatus("paused", {
|
||||
until: nextProcessWindowTime(),
|
||||
seconds: Math.round(msUntilProcessWindow() / 1000),
|
||||
});
|
||||
await waitForProcessWindow();
|
||||
}
|
||||
|
||||
// Sleep between jobs (but not before the first one)
|
||||
if (!first) {
|
||||
const state = getSchedulerState();
|
||||
if (state.job_sleep_seconds > 0) {
|
||||
emitQueueStatus("sleeping", { seconds: state.job_sleep_seconds });
|
||||
const cfg = getScheduleConfig();
|
||||
if (cfg.job_sleep_seconds > 0) {
|
||||
emitQueueStatus("sleeping", { seconds: cfg.job_sleep_seconds });
|
||||
await sleepBetweenJobs();
|
||||
}
|
||||
}
|
||||
@@ -527,17 +529,7 @@ async function runJob(job: Job): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Scheduler ────────────────────────────────────────────────────────────────
|
||||
|
||||
app.get("/scheduler", (c) => {
|
||||
return c.json(getSchedulerState());
|
||||
});
|
||||
|
||||
app.patch("/scheduler", async (c) => {
|
||||
const body = await c.req.json();
|
||||
updateSchedulerState(body);
|
||||
return c.json(getSchedulerState());
|
||||
});
|
||||
// Scheduler endpoints live on /api/settings/schedule now — see server/api/settings.ts.
|
||||
|
||||
// ─── FFmpeg progress parsing ───────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user