# WebSocket Protocol Specification ## Connection ``` ws://localhost:8000/ws?token= ``` **Connection Steps:** 1. Client connects to WebSocket endpoint 2. Server validates JWT token 3. Server sends `connection_established` message 4. Client sends `subscribe` message (optional) 5. Server begins sending data frames **Connection Limits:** - Maximum concurrent connections per user: 3 - Connection timeout (no activity): 5 minutes - Heartbeat interval: 30 seconds --- ## Message Format ### General Structure ```json { "type": "message_type", "timestamp": "2024-01-20T10:30:00.000Z", "data": { ... } } ``` ### All Message Types | Type | Direction | Description | |------|-----------|-------------| | connection_established | Server → Client | Initial connection confirmation | | heartbeat | Bidirectional | Keep-alive ping/pong | | data_frame | Server → Client | Main data payload | | control_frame | Client → Server | Camera/display control | | alert_notification | Server → Client | Real-time alert | | error | Bidirectional | Error reporting | | sync_request | Client → Server | Request full sync | | subscription | Client → Server | Subscribe/unsubscribe channels | --- ## Connection Established **Server → Client** ```json { "type": "connection_established", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "connection_id": "conn_a1b2c3d4", "server_version": "1.0.0", "session_id": "sess_xyz789", "heartbeat_interval": 30, "supported_channels": ["gpu_clusters", "submarine_cables", "ixp_nodes", "alerts"] } } ``` --- ## Heartbeat ### Client → Server (Ping) ```json { "type": "heartbeat", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "ping" } } ``` ### Server → Client (Pong) ```json { "type": "heartbeat", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "pong", "latency_ms": 45 } } ``` **Client Behavior:** - Send ping every 30 seconds - If no pong received in 10 seconds, reconnect - Track latency for monitoring **Server Behavior:** - Send pong immediately on receiving ping - Track connection health --- ## Data Frame (Main Payload) ### Full Update **Server → Client** ```json { "type": "data_frame", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "update_type": "full", "sequence": 12345, "payload": { "meta": { "generated_at": "2024-01-20T10:30:00Z", "data_sources": 9, "total_records": 20800 }, "gpu_clusters": { "total": 1500, "last_updated": "2024-01-20T10:00:00Z", "data": [ { "id": "epoch-gpu-001", "name": "Frontier", "country": "US", "city": "Oak Ridge, TN", "lat": 35.9327, "lng": -84.3107, "gpu_count": 37888, "gpu_type": "AMD MI250X", "total_flops": 1.54e9, "rank": 1, "visual": { "size": 1.0, "color": "#FF6B6B", "pulse": true } } ] }, "submarine_cables": { "total": 436, "last_updated": "2024-01-20T09:00:00Z", "data": [ { "id": "cable-001", "name": "FASTER", "length_km": 11600, "capacity_tbps": 60, "status": "active", "landing_points": [ {"lat": 37.7749, "lng": -122.4194}, {"lat": 35.6762, "lng": 139.6503} ], "visual": { "width": 2.0, "color": "#4ECDC4", "animated": true } } ] }, "ixp_nodes": { "total": 1200, "last_updated": "2024-01-20T09:30:00Z", "data": [ { "id": "ixp-001", "name": "Equinix Ashburn", "country": "US", "city": "Ashburn, VA", "lat": 39.0438, "lng": -77.4874, "member_count": 250, "traffic_tbps": 15.5, "visual": { "size": 0.8, "color": "#45B7D1" } } ] }, "cloud_infra": { "total": 500, "last_updated": "2024-01-20T08:00:00Z", "data": [ { "provider": "AWS", "region": "us-east-1", "data_center_count": 15, "capacity_mw": 500, "lat": 39.0438, "lng": -77.4874, "visual": { "size": 1.2, "color": "#FF9900" } } ] } } } } ``` ### Incremental Update **Server → Client** ```json { "type": "data_frame", "timestamp": "2024-01-20T10:35:00.000Z", "data": { "update_type": "incremental", "sequence": 12346, "base_sequence": 12345, "changes": { "gpu_clusters": { "updated": [ { "id": "epoch-gpu-002", "rank": 2, "gpu_count": 40000 } ], "added": [], "removed": [] }, "alerts": { "new": [ { "id": 1234, "severity": "warning", "message": "API response time > 30s", "source": "Epoch AI" } ], "resolved": [1230] } } } } ``` --- ## Control Frame (Client → Server) ### Camera Position ```json { "type": "control_frame", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "camera_set", "camera": { "position": { "latitude": 35.6762, "longitude": 139.6503, "altitude": 5000000 }, "target": { "latitude": 35.6762, "longitude": 139.6503, "altitude": 0 }, "rotation": { "pitch": -45, "yaw": 0, "roll": 0 } } } } ``` ### Camera Animation ```json { "type": "control_frame", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "camera_animate", "animation": { "type": "fly_to", "target": { "latitude": 39.0438, "longitude": -77.4874, "altitude": 3000000 }, "duration_seconds": 3.0, "easing": "ease_in_out" } } } ``` ### Auto-Cruise Control ```json { "type": "control_frame", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "cruise_control", "enabled": true, "config": { "speed": 1.0, "route": "global", "pause_on_interaction": true } } } ``` ### Layer Visibility ```json { "type": "control_frame", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "layer_visibility", "layers": { "gpu_clusters": true, "submarine_cables": true, "ixp_nodes": true, "cloud_infra": false, "satellites": false, "alerts": true } } } ``` ### Focus Request ```json { "type": "control_frame", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "focus_entity", "entity_type": "gpu_cluster", "entity_id": "epoch-gpu-001", "show_info": true } } ``` ### Time Range Filter ```json { "type": "control_frame", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "set_time_range", "time_range": { "start": "2024-01-01T00:00:00Z", "end": "2024-01-20T23:59:59Z", "aggregation": "hourly" } } } ``` --- ## Alert Notification **Server → Client** ```json { "type": "alert_notification", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "alert": { "id": 1234, "severity": "critical", "title": "Data Collection Failed", "message": "TOP500 data source failed to collect data", "source": "TOP500", "timestamp": "2024-01-20T10:25:00Z", "actions": ["acknowledge", "retry", "view_details"] }, "badge_update": { "critical": 2, "warning": 5, "info": 10 } } } ``` --- ## Sync Request **Client → Server** ```json { "type": "sync_request", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "request_type": "full", "channels": ["gpu_clusters", "submarine_cables", "ixp_nodes"] } } ``` **Server Response:** Same as `data_frame` with `update_type: "full"` --- ## Subscription Management ### Subscribe ```json { "type": "subscription", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "subscribe", "channels": ["gpu_clusters", "alerts"] } } ``` ### Unsubscribe ```json { "type": "subscription", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "unsubscribe", "channels": ["alerts"] } } ``` **Server Response:** ```json { "type": "subscription_confirmed", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "action": "subscribe", "channels": ["gpu_clusters", "alerts"], "active_subscriptions": ["gpu_clusters", "alerts"] } } ``` --- ## Error Messages ### Connection Error ```json { "type": "error", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "code": "INVALID_TOKEN", "message": "Invalid or expired authentication token", "action": "reconnect_with_fresh_token" } } ``` ### Rate Limit Error ```json { "type": "error", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "code": "RATE_LIMITED", "message": "Too many requests", "retry_after_seconds": 30 } } ``` ### Data Error ```json { "type": "error", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "code": "DATA_FETCH_FAILED", "message": "Failed to fetch data from source: Epoch AI", "source": "Epoch AI", "will_retry": true, "retry_in_seconds": 60 } } ``` ### Validation Error ```json { "type": "error", "timestamp": "2024-01-20T10:30:00.000Z", "data": { "code": "INVALID_CONTROL_FRAME", "message": "Invalid camera position", "details": { "field": "camera.position.altitude", "constraint": "Must be positive" } } } ``` --- ## Error Codes Reference | Code | HTTP Equivalent | Description | |------|-----------------|-------------| | INVALID_TOKEN | 401 | JWT validation failed | | TOKEN_EXPIRED | 401 | Token has expired | | RATE_LIMITED | 429 | Too many requests | | CHANNEL_NOT_FOUND | 404 | Invalid channel name | | INVALID_FRAME | 400 | Malformed JSON or structure | | INVALID_CONTROL_FRAME | 400 | Control action validation failed | | DATA_FETCH_FAILED | 500 | Backend data collection failed | | INTERNAL_ERROR | 500 | Server internal error | --- ## Connection State Machine ``` DISCONNECTED │ ├─→ CONNECTING (token validation) │ ├─→ AUTHENTICATED ──→ ESTABLISHED │ │ ├─→ ERROR (reconnect) ├─→ RECEIVING DATA │ │ └───────────────────────────┴─→ DISCONNECTING │ └─→ DISCONNECTED ``` --- ## Reconnection Strategy 1. **Immediate Retry:** On disconnect, retry after 1 second 2. **Exponential Backoff:** If failed, wait 2, 4, 8, 16 seconds 3. **Max Retries:** 5 attempts before giving up 4. **Token Refresh:** If token expired, refresh before reconnecting --- ## Data Flow Diagram ``` ┌──────────┐ ┌──────────┐ │ UE5 │◄───── WebSocket ───►│ Server │ │ Client │ │ │ └────┬─────┘ └────┬─────┘ │ │ │ 1. Connect (with JWT) │ │ 2. Connection Established │ │ │ │ 3. Control Frame (Camera) │ │◄─────────────────────────────────┤ │ │ │ 4. Data Frame (Update) │ │◄─────────────────────────────────┤ │ 5. Heartbeat (30s interval) │ │◄─────────────────────────────────┤ │ │ │ 6. Alert Notification │ │◄─────────────────────────────────┤ ``` --- ## Performance Considerations | Metric | Target | Notes | |--------|--------|-------| | Data frame size | < 1 MB | Compressed if larger | | Update latency | < 5 seconds | End-to-end | | Heartbeat latency | < 100 ms | Server processing | | Max connections | 1000 per server | With负载均衡 | **Optimization Strategies:** - Incremental updates for frequent changes - Binary encoding for large datasets (MessagePack/Protocol Buffers) - Compression for data frames (gzip) - Chunking for large payloads