WebSocket server not wired to HTTP server — issue #2 (ws payment push) is incomplete #15

Closed
opened 2026-03-18 22:21:28 +00:00 by replit · 2 comments
Owner

Context

Issue #2 requires a WebSocket endpoint at ws://host/api/ws so the Three.js Workshop can receive instant payment confirmations instead of polling. The event bus (lib/event-bus.ts) was created and job/session routes now publish events to it. However, no WebSocket server exists yet — nothing is listening on the bus and no clients can connect.

The blocker is architectural: artifacts/api-server/src/index.ts calls app.listen() which returns an http.Server, but the reference is not captured. To attach a ws.Server, we need to refactor to http.createServer(app) and attach the WebSocket server to the same underlying TCP port.

Requirements

  1. Refactor index.ts to use http.createServer(app) and store the server reference
  2. Attach a ws.Server({ server, path: "/api/ws" }) to the same server
  3. On client connect, parse an initial subscription message: { "subscribe": "job", "id": "<jobId>" } or { "subscribe": "session", "id": "<sessionId>" }
  4. Subscribe that socket to the event bus — only forward events matching the subscribed ID
  5. On payment confirmation, send: { "type": "job:paid", "jobId": "...", "invoiceType": "eval|work" }
  6. On state change, send: { "type": "job:state", "jobId": "...", "state": "..." }
  7. On completion, send: { "type": "job:completed", "jobId": "...", "result": "..." }
  8. Handle client disconnects cleanly (remove bus listener, no memory leak)
  9. Heartbeat: send { "type": "ping" } every 30 s; close socket if no pong within 10 s

Acceptance Criteria

  • ws://host/api/ws accepts WebSocket connections
  • A client that subscribes to a job ID receives a job:paid message within 1 s of invoice payment (stub mode)
  • A client that subscribes to a job ID receives a job:completed message when the job finishes
  • Disconnecting a client does not leak event bus listeners (verified via eventBus.listenerCount("bus"))
  • Server starts cleanly with the refactored http.createServer approach
  • Existing HTTP routes (/api/jobs, /api/ui, etc.) continue to work unchanged

Files

  • artifacts/api-server/src/index.ts (refactor to http.createServer)
  • artifacts/api-server/src/lib/ws-server.ts (new — WebSocket handler)
  • artifacts/api-server/src/lib/event-bus.ts (already created)
## Context Issue #2 requires a WebSocket endpoint at `ws://host/api/ws` so the Three.js Workshop can receive instant payment confirmations instead of polling. The event bus (`lib/event-bus.ts`) was created and job/session routes now publish events to it. However, **no WebSocket server exists yet** — nothing is listening on the bus and no clients can connect. The blocker is architectural: `artifacts/api-server/src/index.ts` calls `app.listen()` which returns an `http.Server`, but the reference is not captured. To attach a `ws.Server`, we need to refactor to `http.createServer(app)` and attach the WebSocket server to the same underlying TCP port. ## Requirements 1. Refactor `index.ts` to use `http.createServer(app)` and store the server reference 2. Attach a `ws.Server({ server, path: "/api/ws" })` to the same server 3. On client connect, parse an initial subscription message: `{ "subscribe": "job", "id": "<jobId>" }` or `{ "subscribe": "session", "id": "<sessionId>" }` 4. Subscribe that socket to the event bus — only forward events matching the subscribed ID 5. On payment confirmation, send: `{ "type": "job:paid", "jobId": "...", "invoiceType": "eval|work" }` 6. On state change, send: `{ "type": "job:state", "jobId": "...", "state": "..." }` 7. On completion, send: `{ "type": "job:completed", "jobId": "...", "result": "..." }` 8. Handle client disconnects cleanly (remove bus listener, no memory leak) 9. Heartbeat: send `{ "type": "ping" }` every 30 s; close socket if no pong within 10 s ## Acceptance Criteria - [ ] `ws://host/api/ws` accepts WebSocket connections - [ ] A client that subscribes to a job ID receives a `job:paid` message within 1 s of invoice payment (stub mode) - [ ] A client that subscribes to a job ID receives a `job:completed` message when the job finishes - [ ] Disconnecting a client does not leak event bus listeners (verified via `eventBus.listenerCount("bus")`) - [ ] Server starts cleanly with the refactored `http.createServer` approach - [ ] Existing HTTP routes (`/api/jobs`, `/api/ui`, etc.) continue to work unchanged ## Files - `artifacts/api-server/src/index.ts` (refactor to http.createServer) - `artifacts/api-server/src/lib/ws-server.ts` (new — WebSocket handler) - `artifacts/api-server/src/lib/event-bus.ts` (already created)

[triage] Scope refinement:

  • Files: src/index.ts (HTTP server), lib/event-bus.ts (event system)
  • Acceptance: WebSocket server starts on same HTTP port, clients at ws://host/api/ws receive payment_confirmed events
  • Test: curl upgrade to WS succeeds, mock payment triggers push to connected client
  • Score: 7 (scope=2, acceptance=2, alignment=3 — blocks real-time features)
[triage] Scope refinement: - **Files**: `src/index.ts` (HTTP server), `lib/event-bus.ts` (event system) - **Acceptance**: WebSocket server starts on same HTTP port, clients at `ws://host/api/ws` receive `payment_confirmed` events - **Test**: `curl` upgrade to WS succeeds, mock payment triggers push to connected client - **Score**: 7 (scope=2, acceptance=2, alignment=3 — blocks real-time features)
Author
Owner

Resolved — WebSocket wired to HTTP server in index.ts (attachWebSocketServer)

✅ **Resolved** — WebSocket wired to HTTP server in index.ts (attachWebSocketServer)
This repo is archived. You cannot comment on issues.