3.5 KiB
3.5 KiB
client
(no submodules)
Purpose
Caller-side binding for the worker-RPC protocol. createRawWorkerRpcClient
returns a low-level object exposing .call(method, params, opts) which
returns a Promise<R>; createWorkerRpcClient<T> wraps that in a typed
Proxy<T> so plugin authors invoke remote methods as if they were local
async methods on a typed handle.
The client handles every cross-cutting concern: monotonic correlation-id
allocation, request/response matching, optional AbortSignal forwarding
via cancel frames, optional per-call timeout, budget-enforced backpressure,
outbound queue management, structured-clone safety pre-checks, and
inbound frame validation with version negotiation.
Features
- Typed
Proxy<T>soawait client.method(arg)works without a generated stub. AbortSignalper call; aborting sends acancelframe and rejects the pending promise with anAbortError.- Per-call timeout via
opts.timeoutMsordefaultTimeoutMs. callBudgetcap (default1024) — synchronous-throw exhaustion withWORKER_RPC.BACKPRESSURE.- Pre-send
assertCloneablewalk rejecting functions, class instances, and symbols at the call site instead of letting the platform throw aDataCloneErrorlater. - Inbound frames validated via the Zod protocol schema; invalid
payloads and version mismatches are surfaced through the
onProtocolErrorobserver (never crash the listener). onStreamFramehook to multiplex stream frames into the streaming layer.
Usage: Basic
import { createWorkerRpcClient } from "@suaveplan/api-worker-rpc/client";
interface Calc {
add(a: number, b: number): number;
}
const calc = createWorkerRpcClient<Calc>(workerPort);
const sum = await calc.add(2, 3);
calc.close();
Usage: Advanced
import { createRawWorkerRpcClient } from "@suaveplan/api-worker-rpc/client";
const client = createRawWorkerRpcClient(port, {
callBudget: 256,
defaultTimeoutMs: 5_000,
onProtocolError: (err) => logger.warn({ err }, "rpc protocol error"),
});
const ac = new AbortController();
setTimeout(() => ac.abort(), 200);
try {
const result = await client.call("longRunning", [42], { signal: ac.signal });
} catch (err) {
if (err instanceof Error && err.name === "AbortError") {
// caller cancelled
}
}
client.close("shutdown");
API Reference
createRawWorkerRpcClient(port, opts?): WorkerRpcClient— low-level binding.createWorkerRpcClient<T>(port, opts?): WorkerProxyClient<T>— typed proxy whose__raw__field exposes the underlying client and whoseclose(reason?)tears it down.interface WorkerRpcClient { call, send, cancel, nextId, registry, inFlight, close }.interface WorkerRpcClientOptions { idGenerator?, callBudget?, outboundQueue?, defaultTimeoutMs?, onStreamFrame?, onProtocolError? }.assertCloneable(value, path?): void— re-exported from./cloneable-guard.
Implementation Notes
- The proxy filters reserved keys (
__raw__,close) so they do NOT become remote methods. callacquires a budget slot synchronously before allocating the id so exhaustion fails at the call site, not later in the microtask queue.- The inbound listener catches
parseFrameerrors and routes them toonProtocolErrorrather than throwing — a malformed frame should never crash the host loop. - Cancel frames sent during abort do not require an ack from the server (best-effort cooperative cancel).