2.5 KiB
Handler Bridge
(no submodules)
Purpose
This module owns the shared wire schemas, the worker-side
HandlerRegistry, and the runWithTimeout helper used by both ends of
the proxy. The bridge is the only place that decides how a registered
cron/queued handler is exercised on the worker side; isolating it keeps
the client and server modules small and lets the same logic be unit
tested without spinning up a MessageChannel. Schemas use zod so any
bad payload that crosses the boundary fails fast at the parse step
rather than producing an obscure runtime error downstream.
Features
registerJobRequestSchema/runJobRequestSchema— Zod-validated wire formats for registration and dispatch frames.HandlerRegistry— type-safe storage of cron + queued closures with idempotent set / run / clear semantics and asizesaccessor.runWithTimeout— runs a closure with an optional millisecond budget and wraps every failure into a typedJobsProxyError(HANDLER_THREWorJOB_TIMEOUT).
Usage: Basic
import { HandlerRegistry } from "@suaveplan/api-jobs-worker-proxy/handler-bridge";
const reg = new HandlerRegistry();
reg.setCron("daily-rotate", async () => rotate());
await reg.runCron("daily-rotate");
Usage: Advanced
import { runWithTimeout } from "@suaveplan/api-jobs-worker-proxy/handler-bridge";
await runWithTimeout(
() => longRunningExport(),
"export-csv",
30_000,
); // throws JobsProxyError("JOBS_PROXY.JOB_TIMEOUT") after 30s
API Reference
registerJobRequestSchema: ZodType<RegisterJobRequest>— wire schema.runJobRequestSchema: ZodType<RunJobRequest>— wire schema.HandlerRegistry—setCron,setQueued,hasCron,hasQueued,runCron,runQueued,clear,sizes.runWithTimeout(fn, name, timeoutMs)— runsfn, wraps failures.
Implementation Notes
runWithTimeout uses Promise.race between the handler invocation and
a timeout-rejecting promise. The timeout branch always installs a timer
(non-nullable) when timeoutMs > 0; the finally-clear is unconditional
once that branch is entered. A 0 budget skips the race entirely and
falls back to a direct await so successful handlers do not pay the
extra microtask cost. HandlerRegistry.setCron/setQueued return a
boolean indicating whether the name already existed, allowing callers to
detect (and warn on) duplicate registrations without forbidding the
replacement.