import { getRegistry, type JobRecord } from "./registry"; // Sync jobs that are currently running or queued. Single source of truth for // "is this channel already syncing?" — shared by the cron scheduler // (common/jobs/syncScheduler.ts orchestration) and the manual "Sync all" action // so the two never drift in how they dedup against in-flight work. export function activeSyncJobs(): JobRecord[] { return getRegistry() .list() .filter( (j) => j.kind === "sync" && (j.status === "queued" || j.status === "running") && !!j.channelSlug, ); } export function activeSyncSlugs(): Set { return activeSlugsForKinds(["sync"]); } // The same "is this channel already busy with this kind of work?" question for // any job kind, which is what a bulk fan-out over a channel group needs: the job // registry has NO dedupe of its own, so a second click would happily enqueue a // second whisper-all for the same channel. Kind ids in use here: "sync", // "download-missing", "whisper-all", "digest-channel-local", "backfill-channel". // // activeSyncSlugs() is expressed in terms of this rather than beside it, so the // scheduler's dedupe and a group sweep's can never drift. export function activeSlugsForKinds( kinds: ReadonlyArray, ): Set { const wanted = new Set(kinds); const slugs = new Set(); for (const j of getRegistry().list()) { if (!wanted.has(j.kind)) continue; if (j.status !== "queued" && j.status !== "running") continue; if (!j.channelSlug) continue; slugs.add(j.channelSlug); } return slugs; }