Add Spark Control hardware backend (diarize, queue, discovery)
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
// Passive error reporting to Spark Control's /api/health-event
|
||||
// endpoint. When a hardware-backed transcribe or analyze call fails
|
||||
// (Parakeet 503, vLLM model not found, network timeout to Gemma,
|
||||
// etc.), the relay fires a small POST so the operator's Spark
|
||||
// Control dashboard can surface the failure in real time — without
|
||||
// waiting for its own 5s health-check poll to catch the outage.
|
||||
//
|
||||
// Fire-and-forget: the request is kicked off but NOT awaited by the
|
||||
// caller's error path, so reporting failure to Spark Control never
|
||||
// adds latency to the user's transcribe-failed response.
|
||||
//
|
||||
// Reuses the operator's `relay_spark_control_url` config field
|
||||
// (already used for /api/endpoints discovery). The relay just swaps
|
||||
// the path for /api/health-event, keeping the operator config
|
||||
// surface to one URL.
|
||||
|
||||
import { getConfigSnapshot } from "./config.js";
|
||||
|
||||
const REPORT_TIMEOUT_MS = 3_000;
|
||||
|
||||
// Fire-and-forget. service ∈ { "parakeet", "vllm", "gemma", ... }
|
||||
// matching whatever Spark Control's poller knows about. Errors are
|
||||
// swallowed silently — observability hiccups shouldn't bleed into
|
||||
// the relay's error path.
|
||||
export function reportHealthEvent({ service, ok = false, error, ms }) {
|
||||
// Wrap the actual work in setImmediate so the caller's microtask
|
||||
// queue isn't blocked at all.
|
||||
setImmediate(async () => {
|
||||
try {
|
||||
const cfg = await getConfigSnapshot();
|
||||
const base = (cfg.relay_spark_control_url || "").trim();
|
||||
if (!base) return; // not configured — silent no-op
|
||||
// Strip any path the operator may have configured (they
|
||||
// typically set the /api/endpoints URL) and append health-event.
|
||||
let origin;
|
||||
try {
|
||||
origin = new URL(base).origin;
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
const url = `${origin}/api/health-event`;
|
||||
await fetch(url, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
service,
|
||||
ok,
|
||||
source: "recap-relay",
|
||||
error: typeof error === "string" ? error.slice(0, 280) : null,
|
||||
ms: typeof ms === "number" ? ms : null,
|
||||
}),
|
||||
signal: AbortSignal.timeout(REPORT_TIMEOUT_MS),
|
||||
});
|
||||
} catch {
|
||||
// Best-effort — swallow.
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user