Servarr events: don't crash the runtime when unconfigured

The radarr/sonarr/lidarr/bookshelf events entrypoints built their client
with XClient.fromEnv() at import time, which throws when no API key/URL is
available yet — crash-looping the runtime container. The tools already
guard this; the events entrypoint did not.

Mirror the tools' guard: build the client in a try/catch, and only start
the poll loop when it succeeds. When it fails, log one line and stay idle
until a key is available. Behaviour when configured is unchanged.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
2026-09-05 23:13:56 +02:00
parent 50eb1e6f02
commit 419dd68145
4 changed files with 72 additions and 16 deletions
+18 -4
View File
@@ -14,7 +14,17 @@
import { emit } from "@novox/mesh-sdk/events";
import { RadarrClient, type RadarrQueueItem } from "./client.js";
const radarr = RadarrClient.fromEnv();
// Building the client throws when Radarr has no URL/key yet. Like the tools (see tools/index.ts),
// the events entrypoint must not crash the runtime for that — it stays idle until configured.
function buildClient(): RadarrClient | null {
try {
return RadarrClient.fromEnv();
} catch {
return null;
}
}
const radarr = buildClient();
// Radarr removes an item from the queue once it has been imported; a "warning"/"failed" status is
// how a stuck or broken grab shows itself, so we do not call those a completion when they vanish.
@@ -23,7 +33,7 @@ const FAILED_STATUSES = new Set(["failed", "warning"]);
const inQueue = new Map<number, RadarrQueueItem>();
let primed = false;
async function pollQueue(): Promise<void> {
async function pollQueue(radarr: RadarrClient): Promise<void> {
const { items } = await radarr.getQueue();
const now = new Map(items.map((i) => [i.id, i]));
@@ -50,6 +60,10 @@ const tick = (fn: () => Promise<void>, everyMs: number): void => {
setInterval(run, everyMs);
run();
};
tick(pollQueue, 30_000);
console.log("[radarr] watching the download queue, emitting grabs and completions");
if (radarr) {
tick(() => pollQueue(radarr), 30_000);
console.log("[radarr] watching the download queue, emitting grabs and completions");
} else {
console.log("[radarr] not configured — events idle until an API key is available");
}