111 lines
3.3 KiB
Markdown
111 lines
3.3 KiB
Markdown
# 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`:**
|
|
```javascript
|
|
// 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
|