feat(relay-docker): add self-hosted Docker relay deployment and harden runtime reliability#14
feat(relay-docker): add self-hosted Docker relay deployment and harden runtime reliability#14
Conversation
- fix relay-room init race and serialize ws event handling - harden ws upgrade error handling and close-code mapping - implement graceful async shutdown for registry/relay servers - remove Dockerfile hardcoded registry and sed patching - add relay-shared build artifact packaging and relay-docker smoke tests
There was a problem hiding this comment.
Pull request overview
Adds a new self-hosted Docker deployment option for the relay stack and adjusts shared-package build outputs so the Docker runtime can consume @clawket/shared as compiled ESM with proper dist/package.json metadata.
Changes:
- Introduces
apps/relay-docker(Node HTTP registry +wsrelay in one process) with docs, compose/nginx examples, and runtime smoke tests. - Adds
@clawket/sharedbuild/distribution metadata generation (dist/package.json) and ESM-friendly export specifiers. - Wires
relay-dockerinto the root relay typecheck/test workflows.
Reviewed changes
Copilot reviewed 32 out of 33 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| packages/relay-shared/tsconfig.build.json | Build tsconfig for producing a clean dist/ output (excludes tests). |
| packages/relay-shared/src/index.ts | Switches to ESM-compatible .js export specifier. |
| packages/relay-shared/scripts/write-dist-package-json.mjs | Generates dist/package.json metadata for runtime consumption. |
| packages/relay-shared/package.json | Adds build script to emit dist/ + generated dist/package.json. |
| package.json | Extends relay typecheck/test scripts to include @clawket/relay-docker. |
| apps/relay-docker/tsconfig.json | TypeScript config for the relay-docker workspace. |
| apps/relay-docker/tsconfig.build.json | Build tsconfig for relay-docker (excludes tests). |
| apps/relay-docker/src/server.ts | Process entrypoint that starts registry + relay servers and handles shutdown. |
| apps/relay-docker/src/runtime.test.ts | Smoke tests for health endpoints, pairing, auth rejection close codes, and upgrade error path. |
| apps/relay-docker/src/room-manager.ts | In-memory room routing/GC for gateway rooms. |
| apps/relay-docker/src/relay/utils.ts | Utility helpers (ported) for runtime parsing. |
| apps/relay-docker/src/relay/types.ts | Relay type definitions/constants for the docker runtime. |
| apps/relay-docker/src/relay/telemetry.ts | Structured telemetry logging with basic field filtering. |
| apps/relay-docker/src/relay/storage.ts | Storage/rehydration helpers adapted for the Node/ws shim. |
| apps/relay-docker/src/relay/runtime.ts | Relay runtime state container for docker rooms. |
| apps/relay-docker/src/relay/routing.ts | Message routing and control-plane forwarding logic. |
| apps/relay-docker/src/relay/heartbeat.ts | Alarm/heartbeat scheduling and pruning logic. |
| apps/relay-docker/src/relay/frames.ts | Frame parsing helpers for connect/control flows. |
| apps/relay-docker/src/relay/control.ts | Control envelope parsing/serialization + gateway replacement. |
| apps/relay-docker/src/relay/auth.ts | Token authorization logic using MemoryKV + optional registry verify. |
| apps/relay-docker/src/relay-server.ts | Node HTTP server + ws upgrade handling for the relay endpoint. |
| apps/relay-docker/src/relay-room.ts | Docker port of RelayRoom: initialization serialization + socket event queueing. |
| apps/relay-docker/src/registry.ts | Node HTTP implementation of pairing/verify registry APIs. |
| apps/relay-docker/src/kv-store.ts | In-memory KV with optional better-sqlite3 persistence + TTL GC. |
| apps/relay-docker/src/globals.d.ts | Ambient type declarations intended to fill gaps for Node global fetch-related types. |
| apps/relay-docker/src/cf-shim.ts | Cloudflare Durable Object API shims (storage, alarms, attachments) for Node. |
| apps/relay-docker/README.zh-CN.md | Chinese documentation for docker deployment usage and caveats. |
| apps/relay-docker/README.md | English documentation for docker deployment usage and caveats. |
| apps/relay-docker/package.json | Workspace manifest and scripts for relay-docker. |
| apps/relay-docker/nginx.conf.example | Example reverse-proxy config for registry + relay endpoints. |
| apps/relay-docker/Dockerfile | Multi-stage build for relay-docker runtime image. |
| apps/relay-docker/docker-compose.yml | Compose file for local/self-hosted deployment. |
| apps/relay-docker/.env.example | Example environment configuration for docker deployment. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const onEnd = (): void => { | ||
| try { | ||
| finish({ ok: true, data: JSON.parse(Buffer.concat(chunks).toString()) as T }); | ||
| } catch { | ||
| finish({ ok: true, data: null }); | ||
| } | ||
| }; | ||
|
|
||
| const onError = (): void => { | ||
| finish({ ok: true, data: null }); | ||
| }; |
There was a problem hiding this comment.
readJsonBodyLimited treats invalid JSON (and request stream errors) as { ok: true, data: null }. For endpoints like POST /v1/pair/register, this means malformed JSON bodies still succeed and create pairing records with default values. Consider returning { ok: false, status: 400, body: { error: { code: 'INVALID_JSON', message: 'Invalid JSON body' }}} when parsing fails (and possibly distinguishing empty body vs malformed body).
Summary
This PR introduces a self-hosted Docker deployment for relay services and includes follow-up hardening from review feedback to improve runtime safety, shutdown behavior, and packaging reliability.
Changes
1. Add relay-docker self-hosted stack
2. Improve websocket and runtime safety
3. Improve graceful shutdown
4. Improve Docker and package build reliability
5. Add tests and workspace integration
Validation
Commit Breakdown
Notes for Reviewers