@assistant-ui/pinboard
v0.3.0
Published
Pinned control plane: directory, placement, and HTTP proxy
Readme
pinboard
The pinned control plane: a stateless Node service that owns the directory (which backend holds which id) and proxies all data-plane traffic to the right backend. Any number of nodes behind one LB URL; coordination via Redis. Plain Node: node:http + undici + ioredis.
Running
npm install && npm run build
PINBOARD_TOKEN=... REDIS_URL=redis://localhost:6379 npm startEnv: PORT (8080), REDIS_URL (memory: = in-process store for dev/tests), PINBOARD_TOKEN (required; Bearer on /registry/*), PINBOARD_LEASE_TTL_MS (10000). npm test needs no Redis.
How it works
Non-/registry requests hit the catch-all proxy: longest registered namespace prefix → next segment is the id → look up pinboard:place:{ns}:{sha256(id)} in Redis. Live worker: stream through (SSE-safe). Stale entry (worker record expired): clientId-guarded delete, then fresh placement — pick 2 random live workers, take the one with more headroom, claim with SET NX (the singleton guarantee). Sticky, no rebalancing.
Workers POST /registry/register at boot — the full worker record; the response mints a sessionId and returns expiresInMs (the record TTL, i.e. the re-place deadline). POST /registry/heartbeat ~every 3s — { sessionId, headroom, draining } renews the record for another full window; an unknown session is a 409 { reregister: true } NACK telling the worker to abort its instances and reregister, a superseded session is a 409 { superseded: true }. Booting against an empty registry writes pinboard:boot_epoch and new placements are refused (503 + Retry-After) for one full record TTL. POST /registry/release frees a placement. Pinboard pushes evict / wind_down / resume as HTTP callbacks to the worker's <advertiseUrl>/_pinned/*, authed with the worker's own secret. Body shapes and Redis keys are documented where they're defined: src/registry.ts, src/proxy.ts, and the tests.
Introspection (Bearer): GET /registry/workers, GET /registry/overview (workers plus per-namespace placed entries and this node's in-flight proxied connection counts), POST /registry/push; GET /healthz unauthenticated.
Observability
Structured JSON logs on stdout via pino; LOG_LEVEL (default info), pretty-printed when NODE_ENV=development. GET /metrics (unauthenticated, like /healthz) serves Prometheus metrics prefixed pinboard_: HTTP request counts and durations by normalized route, placement resolution outcomes, forwards, in-flight data-plane connections, registered workers, active placements, event-loop lag, and Node process defaults. GET /readyz returns { status, uptimeSeconds, workers } — 200 when serving, 503 while booting or draining. A heartbeat line (uptime, workers, memory, event-loop lag) logs every 60s; uncaught exceptions log fatal and exit.
