3.4 KiB
Worker-Side Jobs Proxy Client
(no submodules)
Purpose
createJobsProxyClient(port, opts) is the worker-tier entry point for the
@suaveplan/api-jobs-worker-proxy package. It returns an object that
implements the JobRegistrationHandle capability slot from
@suaveplan/api-types, letting a worker-isolated API plugin register
cron and queued jobs even though the actual scheduler runs in the host
main process. Every registerCron and registerQueued call stores the
handler in a local HandlerRegistry and asynchronously marshals a
registerJob RPC to the main side via the supplied MessagePort. When
the main scheduler ticks a job, the same port carries a runJob
dispatch back to the worker; the local serve-side listener invokes the
stored handler under an optional timeout.
Features
- Implements the exact
JobRegistrationHandlesurface (registerCron,registerQueued) — no proxy-specific extensions on the public type. - Bidirectional over a single port: outbound registration RPCs +
inbound
runJobdispatch via paired raw RPC client + serve handler. - Fire-and-forget registration semantics with an
onHandlerErrorobserver for asynchronous rejections (job-not-declared, port closed). - Per-handler timeout via
handlerTimeoutMs; long-running closures reject withJOBS_PROXY.JOB_TIMEOUT. - Idempotent
close(reason?)tears down both the RPC client and the serve listener.
Usage: Basic
import { MessageChannel } from "node:worker_threads";
import { createJobsProxyClient } from "@suaveplan/api-jobs-worker-proxy/worker-side";
const channel = new MessageChannel();
const client = createJobsProxyClient(channel.port1);
client.registerCron("rotate-keys", async () => {
await rotate();
});
Usage: Advanced
import { createJobsProxyClient } from "@suaveplan/api-jobs-worker-proxy/worker-side";
const client = createJobsProxyClient(workerPort, {
handlerTimeoutMs: 30_000,
onHandlerError: (err, ctx) => {
logger.warn({ code: err.code, name: ctx.name, kind: ctx.kind });
},
});
client.registerQueued("send-email", async (payload) => {
await mailer.send(payload as MailPayload);
});
API Reference
createJobsProxyClient(port, opts?) -> JobsProxyClient— factory.JobsProxyClient extends JobRegistrationHandle— addsclose()and asizesaccessor reporting registration counts.JobsProxyClientOptions:handlerTimeoutMs?: number— per-dispatch timeout,0disables.onHandlerError?: (err, ctx) => void— observer hook.
Implementation Notes
The client multiplexes a createRawWorkerRpcClient (for outbound
registerJob calls) and a serveWorkerRpc handlers object (for inbound
runJob) over the same PortLike. Protocol frames partition cleanly:
response frames target the RPC client's pending registry, and
request frames target the serve dispatcher; each listener silently
drops the other's traffic. The local HandlerRegistry is the single
source of truth for which handlers can be dispatched — the main side
relies on the worker holding the closure and we never serialize the
function across the wire. The fire-and-forget registerJob call uses
.catch to funnel rejections (including JOB_NOT_DECLARED from main)
through onHandlerError, preserving the original JobRegistrationHandle
synchronous-void return contract.