Skip to content

feat: Implement WebSocket server endpoint#6

Open
charliewwdev wants to merge 4 commits intomainfrom
feat/implement-websocket-server-endpoint
Open

feat: Implement WebSocket server endpoint#6
charliewwdev wants to merge 4 commits intomainfrom
feat/implement-websocket-server-endpoint

Conversation

@charliewwdev
Copy link
Copy Markdown
Member

Create a WebSocket server handler that accepts client connections, manages subscriptions per metric stream, and broadcasts updates on data change. Support graceful disconnects.


Generated by OpenDev AI

The implementation is split into three concerns:

  1. src/types/metrics.ts — Shared wire-protocol types (MetricData, ClientMessage, ServerMessage) kept in their own file so both the server and tests can import them without circular dependencies.

  2. src/ws-server.ts — Two exported classes:

    • MetricBroadcaster: pure subscription-management logic (no I/O). Maintains a Map<stream, Set<TrackedClient>> and a reverse Set<string> on each client so both subscribe/unsubscribe and full removeClient are O(n) in subscribers rather than O(streams × subscribers).
    • MetricWebSocketServer: wraps an http.Server + WebSocketServer so the port is injected at listen() time (port 0 works for tests). Handles the JSON wire protocol (subscribe / unsubscribe / ping), enforces a 64 KB message cap, validates stream names against a strict regex to block path-traversal strings, and attaches to NATS via the dev.metrics.> wildcard subject. A 30-second ping/pong heartbeat loop terminates clients whose TCP connections dropped silently. Graceful shutdown sends a 1001 Going Away close frame before tearing down the server.
  3. package.json — Adds ws (^8.17.0) to dependencies and @types/ws to devDependencies, the only new dependency required.

Key design decisions:

  • The MetricBroadcaster / MetricWebSocketServer split makes unit-testing the subscription logic trivial with plain mock objects, while integration tests exercise real WebSocket connections on an OS-assigned port.
  • NATS subject dev.metrics.<stream> mirrors the existing dev.agent.* and dev.deploy.* naming conventions in the codebase.
  • The heartbeat timer is .unref()'d so it never prevents the Node process from exiting cleanly in tests or during shutdown.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant