3.0 KiB
control-channel
(no submodules)
Purpose
Bidirectional control plane: the main process tells a worker-isolated
plugin to stop or resume emitting log records. The host calls disable
during plugin shutdown so a worker that is still draining its work
queue does not keep producing records after the main-side sink has been
torn down (design doc §5.5 — components dispose in reverse dependency
order). Without this channel the main-side sink would either log to a
zombie sink (silent loss with no diagnostic) or panic on a closed port.
Frames are simple: { kind: "control", action: "disable" | "enable" }.
There is no acknowledgement frame; the channel is fire-and-forget. The
worker maintains a shared ControlState object the proxy client checks
synchronously on every log call, so a disable received between two
calls correctly suppresses the second.
Features
createControlChannelSender(port)— returns{ disable, enable }thunks usable from the main process.mountControlChannelReceiver(port, options?)— installs a listener on the worker-side port; returns the sharedControlStateplus adisposethunk. Tolerates malformed frames (silent drop) so a hostile or buggy host cannot crash the worker.onChangecallback fires only on real transitions, not on repeated same-value frames.
Usage: Basic
// Main side
import { createControlChannelSender } from "@suaveplan/api-logger-worker-proxy/control-channel";
const ctl = createControlChannelSender(mainPort);
ctl.disable();
// ... main-side sink torn down ...
worker.terminate();
// Worker side
import { mountControlChannelReceiver } from "@suaveplan/api-logger-worker-proxy/control-channel";
const ctl = mountControlChannelReceiver(workerPort);
// log.info() etc. read ctl.state.enabled synchronously
Usage: Advanced
Observe transitions to flush in-flight batches and surface a counter:
import { mountControlChannelReceiver } from "@suaveplan/api-logger-worker-proxy/control-channel";
const ctl = mountControlChannelReceiver(port, {
onChange: (enabled) => {
if (!enabled) batcher.flush();
meter.add(`logger_proxy.control_state.${enabled ? "on" : "off"}`, 1);
},
});
API Reference
createControlChannelSender(port: PortLike): ControlChannelSender— emits{ v, kind: "control", action }frames.mountControlChannelReceiver(port, options?)— returns{ state: Readonly<ControlState>, dispose }.ControlState—{ enabled: boolean }. Defaults totrueso workers emit normally until told otherwise.
Implementation Notes
The receiver shares the port with goodbye and (incidentally) with the
worker-side log emit path — frames whose kind is not "control" are
ignored so the receiver composes cleanly with other listeners on the
same port. The state object is mutated in place (not replaced) so the
proxy client can capture a stable reference at construction time and
not need to re-resolve a getter on the per-call hot path.