brackt/plans/completed/phase-3-socket-implementation-summary.md
Chris Parsons 35fe84a1dd
Update claude.md to push more tests. (#84)
* Update claude.md to push more tests.

* Archiving old plans.

* fix: run DB migrations programmatically on server startup

Replace unreliable drizzle-kit CLI migration with drizzle-orm's built-in
migrator running in the server process before accepting connections. This
ensures migrations are always applied on deploy and fails fast if they error.

- Add runMigrations() to server.ts using drizzle-orm/postgres-js/migrator
- Skip migrations in development (handled manually via db:migrate)
- Add DATABASE_URL guard with a clear error message
- Remove start:production script (now identical to start)
- Update Dockerfile CMD to use npm run start

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 22:31:04 -08:00

3.3 KiB

Phase 3: Socket.IO Implementation - Summary

Key Decision: Modify server.js (Option A)

After researching React Router v7 + Socket.IO integration patterns, the recommended approach is:

Why This Approach?

  1. Industry Standard: Socket.IO requires http.createServer(app) - this is the documented pattern
  2. Single Port: HTTP and WebSocket traffic on same port (simpler deployment)
  3. No CORS Issues: Everything runs on same origin
  4. Works with SSR: Compatible with React Router v7's server-side rendering
  5. Simpler Deployment: One process, one port, one service

What Changes?

Minimal changes to server.js:

// Before:
app.listen(PORT, () => {...});

// After:
import { createServer } from "http";
const httpServer = createServer(app);
const { initializeSocketIO } = await import("./server/socket.js");
initializeSocketIO(httpServer);
httpServer.listen(PORT, () => {...});

That's it! Just 4 lines changed in server.js.

Alternative Considered: Separate Socket Server (Option B)

Why we rejected this:

  • Requires managing two processes
  • CORS configuration complexity
  • Different ports (3000 for HTTP, 3001 for WebSocket)
  • More complex deployment (two services)
  • Not the standard pattern

When to use Option B:

  • If you absolutely cannot modify server.js
  • If you need to scale WebSocket separately from HTTP
  • If you're using a microservices architecture

Implementation Steps

Step 1: Create Socket Module

  • File: server/socket.js (not .ts to avoid bundling)
  • Exports: initializeSocketIO() and getSocketIO()
  • Stores instance globally for route handlers

Step 2: Modify server.js

  • Import http.createServer
  • Create HTTP server from Express app
  • Initialize Socket.IO with HTTP server
  • Call httpServer.listen() instead of app.listen()

Step 3: Client Hook

  • Create app/hooks/useDraftSocket.ts
  • Handles connection/disconnection
  • Auto-joins draft room on connect
  • Provides on/off helpers for events

Step 4: Route Handlers

  • Import getSocketIO() in API routes
  • Emit events after database writes
  • Example: After creating pick, emit pick-made to room

Event Architecture

Write Operations → HTTP POST

  • Making picks
  • Queue management
  • Commissioner actions
  • Reason: Reliability, error handling, validation

Read Operations → Socket.IO Broadcast

  • Pick made notifications
  • Timer updates
  • Draft status changes
  • Reason: Real-time updates to all clients

Testing Checklist

  • Server starts with "Socket.IO initialized"
  • Browser console shows "Connected to Socket.IO"
  • Server logs show "Client connected: [id]"
  • Multiple clients can join same draft room
  • Picks broadcast to all clients in room
  • Disconnection handled gracefully

Production Notes

  • Socket.IO auto-upgrades from polling → WebSocket
  • Load balancer needs sticky sessions for WebSocket
  • Monitor connection counts
  • Consider Redis adapter for horizontal scaling (future)

Files Created/Modified

New Files:

  • server/socket.js - Socket.IO initialization
  • server/types.d.ts - TypeScript globals
  • app/hooks/useDraftSocket.ts - Client hook

Modified Files:

  • server.js - 4 lines changed (http.createServer)
  • tsconfig.node.json - Add server directory

Total LOC: ~150 lines of new code