Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit 00f8b1b8c6417689c1391862508f0f1091bbc35f
parent 185ad18d52f584424567c52178adb5094bacd0cb
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Fri, 25 Sep 2026 11:04:31 -0400

common: auto-download skips a deferred video; idleReason "deferred"

The download pick drops ids whose rate-limit deferral is live, so after a
cooldown the runner moves on to the next video. When that leaves nothing,
the lane idles "deferred" (cooldown still wins). Boot prunes lapsed
deferrals. dispatch.ts gains the sentence "every pending video was
rate-limited recently and is deferred". Manual Sync / download-missing do
not consult deferrals.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Diffstat:
Mcommon/controller/autoRunner.ts | 33+++++++++++++++++++++++++++++++--
Meditor/app/operations/components/dispatch.ts | 2++
2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/common/controller/autoRunner.ts b/common/controller/autoRunner.ts @@ -67,7 +67,12 @@ import { recordPick, writeAutoQueueState, } from "../jobs/autoQueueState"; -import { isCoolingDown, pruneExpired } from "../jobs/platformBackoff"; +import { + isCoolingDown, + isVideoDeferred, + pruneDeferred, + pruneExpired, +} from "../jobs/platformBackoff"; import { applyUnitOutcome } from "../jobs/unitOutcome"; import { type DownloadFailureClass } from "../lib/availability"; import { resolveCookiePolicy } from "../lib/cookiePolicy"; @@ -204,6 +209,9 @@ export type AutoRunnerIdleReason = // Every pending video belongs to a platform inside a rate-limit/network // cooldown window. Download only. | "cooldown" + // Every pending video left after the platform gates was rate-limited + // recently and is deferred (videoDeferrals). Download only. + | "deferred" // No enabled, non-degraded worker slot exists. Transcription only. | "no-workers" // The worker pool is pause-all'd. Transcription only, and DISTINCT from @@ -1148,6 +1156,9 @@ async function runLoop( // Drop long-lapsed platform cooldowns on boot; entries still in (or recently // out of) their window are kept so an Odysee 429 cooldown survives a restart. pruneExpired(kindState.platformBackoff, Date.now()); + // And lapsed per-video deferrals (live ones survive a restart by design — a + // restart must not re-hit the rate-limited video at fails+1). + pruneDeferred(kindState.videoDeferrals, Date.now()); // The session's "already done, do not re-pick" set, KEYED BY (operation, // video) rather than by video. // @@ -1613,6 +1624,9 @@ async function runLoop( // download (busy) OR is in a rate-limit/network backoff window (cooling // down), so a busy/throttled platform yields to the next-priority free one. let anyCooling = false; + // Download only: some pending video was dropped because it is deferred + // after a recent rate limit (see unitOutcome.ts). + let anyDeferred = false; platformSkip.clear(); if (kind === "download") { // Merge in any cooldown a manual sync/import wrote to the shared state @@ -1649,6 +1663,17 @@ async function runLoop( }); } } + // A video rate-limited recently is skipped until its deferral lapses, so + // after a cooldown the runner moves on rather than re-picking it. + if (Object.keys(kindState.videoDeferrals).length > 0) { + for (const leafId of Object.keys(pending)) { + pending[leafId] = pending[leafId].filter((id) => { + if (!isVideoDeferred(kindState.videoDeferrals, id, now)) return true; + anyDeferred = true; + return false; + }); + } + } } // ── THE SCAN COMES BEFORE THE DOWNLOADS ──────────────────────────────── @@ -1734,7 +1759,11 @@ async function runLoop( // platform gates just took away — the page says which. if (pendingBeforeGates === 0) live.idleReason = "no-pending"; else if (countPending(pending) === 0) { - live.idleReason = anyCooling ? "cooldown" : "capped"; + live.idleReason = anyCooling + ? "cooldown" + : anyDeferred + ? "deferred" + : "capped"; } else live.idleReason = "capped"; return null; } diff --git a/editor/app/operations/components/dispatch.ts b/editor/app/operations/components/dispatch.ts @@ -151,6 +151,8 @@ export function idleReasonText( return "work exists, but every route to it is at a worker cap"; case "cooldown": return "every pending platform is in a rate-limit cooldown"; + case "deferred": + return "every pending video was rate-limited recently and is deferred"; case "no-workers": return "no enabled worker to run it"; case "workers-paused":