|
| 1 | +# WebSocket Real-Time Inventory Updates |
| 2 | + |
| 3 | +## Overview |
| 4 | +This implementation provides real-time inventory updates using WebSockets. When inventory changes occur, all connected clients receive instant notifications about stock adjustments and low stock alerts. |
| 5 | + |
| 6 | +## Features |
| 7 | + |
| 8 | +### 1. Real-Time Inventory Updates |
| 9 | +- Instant notifications when inventory is adjusted |
| 10 | +- Broadcasts to all connected clients simultaneously |
| 11 | +- Includes product ID, warehouse ID, quantity, and action type |
| 12 | + |
| 13 | +### 2. Low Stock Alerts |
| 14 | +- Automatic alerts when stock falls below minimum threshold |
| 15 | +- Includes product name and current vs. minimum stock levels |
| 16 | +- Can trigger browser notifications |
| 17 | + |
| 18 | +### 3. Multi-Client Support |
| 19 | +- Supports unlimited concurrent WebSocket connections |
| 20 | +- Thread-safe connection management |
| 21 | +- Automatic reconnection handling |
| 22 | + |
| 23 | +## WebSocket Endpoint |
| 24 | + |
| 25 | +**URL:** `ws://localhost:3000/ws/inventory` |
| 26 | + |
| 27 | +**Protocol:** WebSocket (ws://) |
| 28 | + |
| 29 | +## Message Types |
| 30 | + |
| 31 | +### 1. Inventory Update |
| 32 | +Sent when inventory is created, updated, or adjusted. |
| 33 | + |
| 34 | +```json |
| 35 | +{ |
| 36 | + "type": "inventory_update", |
| 37 | + "inventory_id": 123, |
| 38 | + "product_id": 45, |
| 39 | + "warehouse_id": 2, |
| 40 | + "quantity": 150, |
| 41 | + "action": "adjusted", |
| 42 | + "timestamp": "2026-02-13T10:30:45Z" |
| 43 | +} |
| 44 | +``` |
| 45 | + |
| 46 | +**Actions:** |
| 47 | +- `created` - New inventory record created |
| 48 | +- `updated` - Existing inventory updated |
| 49 | +- `adjusted` - Inventory adjusted via `/inventory/adjust` endpoint |
| 50 | +- `deleted` - Inventory record deleted |
| 51 | + |
| 52 | +### 2. Low Stock Alert |
| 53 | +Sent when inventory quantity falls at or below the minimum stock level. |
| 54 | + |
| 55 | +```json |
| 56 | +{ |
| 57 | + "type": "low_stock_alert", |
| 58 | + "product_id": 45, |
| 59 | + "warehouse_id": 2, |
| 60 | + "current_quantity": 8, |
| 61 | + "min_stock": 10, |
| 62 | + "product_name": "Widget A", |
| 63 | + "timestamp": "2026-02-13T10:30:45Z" |
| 64 | +} |
| 65 | +``` |
| 66 | + |
| 67 | +## Usage |
| 68 | + |
| 69 | +### JavaScript Client Example |
| 70 | + |
| 71 | +```javascript |
| 72 | +// Connect to WebSocket |
| 73 | +const ws = new WebSocket('ws://localhost:3000/ws/inventory'); |
| 74 | + |
| 75 | +// Connection opened |
| 76 | +ws.onopen = () => { |
| 77 | + console.log('Connected to inventory updates'); |
| 78 | +}; |
| 79 | + |
| 80 | +// Listen for messages |
| 81 | +ws.onmessage = (event) => { |
| 82 | + const data = JSON.parse(event.data); |
| 83 | + |
| 84 | + if (data.type === 'inventory_update') { |
| 85 | + console.log(`Inventory updated: Product ${data.product_id}, Quantity: ${data.quantity}`); |
| 86 | + } else if (data.type === 'low_stock_alert') { |
| 87 | + console.log(`Low stock alert: ${data.product_name} - ${data.current_quantity}/${data.min_stock}`); |
| 88 | + } |
| 89 | +}; |
| 90 | + |
| 91 | +// Handle errors |
| 92 | +ws.onerror = (error) => { |
| 93 | + console.error('WebSocket error:', error); |
| 94 | +}; |
| 95 | + |
| 96 | +// Connection closed |
| 97 | +ws.onclose = () => { |
| 98 | + console.log('Disconnected from server'); |
| 99 | +}; |
| 100 | +``` |
| 101 | + |
| 102 | +### Demo HTML Client |
| 103 | + |
| 104 | +A fully functional demo HTML client is available at: |
| 105 | +**`web/inventory-realtime.html`** |
| 106 | + |
| 107 | +To use: |
| 108 | +1. Start the server: `go run main.go` |
| 109 | +2. Open `web/inventory-realtime.html` in your browser |
| 110 | +3. Click "Connect" to establish WebSocket connection |
| 111 | +4. Make inventory changes via API endpoints to see real-time updates |
| 112 | + |
| 113 | +## Testing the WebSocket |
| 114 | + |
| 115 | +### Step 1: Start the Server |
| 116 | +```bash |
| 117 | +go mod tidy # Install dependencies including gorilla/websocket |
| 118 | +go run main.go |
| 119 | +``` |
| 120 | + |
| 121 | +### Step 2: Connect a Client |
| 122 | +Open the demo HTML client or create your own WebSocket connection to `ws://localhost:3000/ws/inventory` |
| 123 | + |
| 124 | +### Step 3: Trigger Updates |
| 125 | +Use the REST API to make inventory changes: |
| 126 | + |
| 127 | +```bash |
| 128 | +# Adjust inventory (will trigger WebSocket broadcast) |
| 129 | +curl -X POST http://localhost:3000/inventory/adjust \ |
| 130 | + -H "Content-Type: application/json" \ |
| 131 | + -d '{ |
| 132 | + "product_id": 1, |
| 133 | + "warehouse_id": 1, |
| 134 | + "quantity": -5, |
| 135 | + "reason": "Sale" |
| 136 | + }' |
| 137 | +``` |
| 138 | + |
| 139 | +### Step 4: Observe Real-Time Updates |
| 140 | +All connected WebSocket clients will receive the update instantly! |
| 141 | + |
| 142 | +## Architecture |
| 143 | + |
| 144 | +### Components |
| 145 | + |
| 146 | +1. **Hub (`internal/websocket/hub.go`)** |
| 147 | + - Manages all active WebSocket connections |
| 148 | + - Broadcasts messages to all clients |
| 149 | + - Handles client registration/unregistration |
| 150 | + - Thread-safe operations using mutex |
| 151 | + |
| 152 | +2. **Client (`internal/websocket/client.go`)** |
| 153 | + - Represents individual WebSocket connection |
| 154 | + - Handles read/write operations |
| 155 | + - Implements ping/pong for connection health |
| 156 | + - Automatic cleanup on disconnect |
| 157 | + |
| 158 | +3. **Handler (`internal/websocket/handler.go`)** |
| 159 | + - HTTP to WebSocket upgrade |
| 160 | + - Global hub instance management |
| 161 | + - Connection request handling |
| 162 | + |
| 163 | +4. **Integration (`internal/inventory/handlers.go`)** |
| 164 | + - Broadcasts updates after inventory changes |
| 165 | + - Checks for low stock conditions |
| 166 | + - Integrates seamlessly with existing handlers |
| 167 | + |
| 168 | +## Configuration |
| 169 | + |
| 170 | +### Connection Settings |
| 171 | +Defined in `internal/websocket/client.go`: |
| 172 | + |
| 173 | +```go |
| 174 | +writeWait = 10 * time.Second // Write timeout |
| 175 | +pongWait = 60 * time.Second // Read timeout |
| 176 | +pingPeriod = 54 * time.Second // Ping interval |
| 177 | +maxMessageSize = 512 // Max message size |
| 178 | +``` |
| 179 | + |
| 180 | +### CORS Settings |
| 181 | +Currently allows all origins (development mode). For production, modify `internal/websocket/handler.go`: |
| 182 | + |
| 183 | +```go |
| 184 | +var upgrader = websocket.Upgrader{ |
| 185 | + CheckOrigin: func(r *http.Request) bool { |
| 186 | + // Restrict to specific origins in production |
| 187 | + origin := r.Header.Get("Origin") |
| 188 | + return origin == "https://yourdomain.com" |
| 189 | + }, |
| 190 | +} |
| 191 | +``` |
| 192 | + |
| 193 | +## Production Considerations |
| 194 | + |
| 195 | +1. **CORS Configuration** |
| 196 | + - Restrict `CheckOrigin` to trusted domains |
| 197 | + - Implement authentication tokens |
| 198 | + |
| 199 | +2. **Rate Limiting** |
| 200 | + - Add rate limiting to prevent abuse |
| 201 | + - Limit connections per IP/user |
| 202 | + |
| 203 | +3. **Message Filtering** |
| 204 | + - Allow clients to subscribe to specific products/warehouses |
| 205 | + - Reduce unnecessary bandwidth |
| 206 | + |
| 207 | +4. **Monitoring** |
| 208 | + - Track active connections count |
| 209 | + - Monitor message throughput |
| 210 | + - Log connection/disconnection events |
| 211 | + |
| 212 | +5. **SSL/TLS** |
| 213 | + - Use `wss://` instead of `ws://` in production |
| 214 | + - Implement proper certificate management |
| 215 | + |
| 216 | +## Troubleshooting |
| 217 | + |
| 218 | +### WebSocket Connection Fails |
| 219 | +- Ensure server is running on port 3000 |
| 220 | +- Check firewall settings |
| 221 | +- Verify URL is correct: `ws://localhost:3000/ws/inventory` |
| 222 | + |
| 223 | +### No Updates Received |
| 224 | +- Verify WebSocket connection is established |
| 225 | +- Check server logs for broadcast messages |
| 226 | +- Ensure inventory changes are being made through the API |
| 227 | + |
| 228 | +### Connection Drops |
| 229 | +- Check network stability |
| 230 | +- Increase `pongWait` timeout if needed |
| 231 | +- Implement client-side reconnection logic |
| 232 | + |
| 233 | +## Future Enhancements |
| 234 | + |
| 235 | +- [ ] Client-side filtering (subscribe to specific products) |
| 236 | +- [ ] Authentication/Authorization |
| 237 | +- [ ] Message history/replay |
| 238 | +- [ ] Compression for large broadcasts |
| 239 | +- [ ] Horizontal scaling with Redis pub/sub |
| 240 | +- [ ] WebSocket connection metrics dashboard |
| 241 | + |
| 242 | +## Dependencies |
| 243 | + |
| 244 | +- **gorilla/websocket** v1.5.3 - High-performance WebSocket library |
| 245 | + |
| 246 | +Install with: |
| 247 | +```bash |
| 248 | +go get github.com/gorilla/websocket@v1.5.3 |
| 249 | +go mod tidy |
| 250 | +``` |
0 commit comments