Initial Commit
This commit is contained in:
99
packages/api-stack/api/api-worker-rpc/src/client/client.md
Normal file
99
packages/api-stack/api/api-worker-rpc/src/client/client.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# `client`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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>` so `await client.method(arg)` works without a
|
||||
generated stub.
|
||||
- `AbortSignal` per call; aborting sends a `cancel` frame and rejects
|
||||
the pending promise with an `AbortError`.
|
||||
- Per-call timeout via `opts.timeoutMs` or `defaultTimeoutMs`.
|
||||
- `callBudget` cap (default `1024`) — synchronous-throw exhaustion
|
||||
with `WORKER_RPC.BACKPRESSURE`.
|
||||
- Pre-send `assertCloneable` walk rejecting functions, class
|
||||
instances, and symbols at the call site instead of letting the
|
||||
platform throw a `DataCloneError` later.
|
||||
- Inbound frames validated via the Zod protocol schema; invalid
|
||||
payloads and version mismatches are surfaced through the
|
||||
`onProtocolError` observer (never crash the listener).
|
||||
- `onStreamFrame` hook to multiplex stream frames into the streaming
|
||||
layer.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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 whose
|
||||
`close(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.
|
||||
- `call` acquires 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 `parseFrame` errors and routes
|
||||
them to `onProtocolError` rather 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).
|
||||
Reference in New Issue
Block a user