Our system implements a hybrid architecture combining traditional REST APIs with real-time WebSocket connections, utilizing both MySQL and Firebase for different aspects of the application.
graph TD
Client[Client Application]
API[REST API]
WS[WebSocket Server]
MySQL[(MySQL Database)]
Firebase[(Firebase Realtime DB)]
PubSub[Phoenix PubSub]
Client --> API
Client --> WS
API --> MySQL
WS --> PubSub
PubSub --> Firebase
PubSub --> WS
API --> Firebase
The REST API handles:
- User authentication and authorization
- CRUD operations for comments
- User management
- Device management
Key modules:
AuthController
: Handles user authenticationCommentController
: Manages comment operationsGuardian
: JWT token management
WebSocket connections manage:
- Real-time comment updates
- Presence tracking
- Live synchronization with Firebase
Key modules:
UserSocket
: WebSocket connection managementCommentChannel
: Real-time comment broadcastingPresence
: User presence tracking
Stores:
- User accounts
- Comments
- Device information
- Authentication data
Schema overview:
users
- id (uuid)
- email (string)
- username (string)
- password_hash (string)
- last_login_at (timestamp)
- is_active (boolean)
comments
- id (uuid)
- content (text)
- video_id (string)
- user_id (uuid, fk)
- inserted_at (timestamp)
- updated_at (timestamp)
user_devices
- id (uuid)
- user_id (uuid, fk)
- device_id (string)
- last_seen_at (timestamp)
- device_info (jsonb)
- is_active (boolean)
Stores:
- Real-time comment data
- User presence information
Phoenix PubSub handles:
- Broadcasting comments to connected clients
- Synchronizing presence information
- Coordinating between multiple server nodes
sequenceDiagram
participant Client
participant API
participant Guardian
participant MySQL
participant Firebase
Client->>API: Login Request
API->>MySQL: Verify Credentials
MySQL-->>API: User Data
API->>Guardian: Generate JWT
Guardian-->>API: JWT Token
API->>Firebase: Update Presence
API-->>Client: JWT + User Data
sequenceDiagram
participant Client
participant WebSocket
participant PubSub
participant MySQL
participant Firebase
Client->>WebSocket: Connect (with JWT)
WebSocket->>Client: Connection Established
Client->>WebSocket: Join Comment Channel
WebSocket->>PubSub: Subscribe to Updates
Client->>WebSocket: New Comment
WebSocket->>MySQL: Save Comment
WebSocket->>PubSub: Broadcast Comment
PubSub->>Firebase: Sync Comment
PubSub->>WebSocket: Broadcast to Clients
WebSocket->>Client: Comment Update
- JWT-based authentication using Guardian
- Token refresh mechanism
- Device-based authentication
- Rate limiting per user/device
- Role-based access control
- Resource-level permissions
- Channel-level authorization
- Encrypted connections (SSL/TLS)
- Hashed passwords (Argon2)
- Input validation and sanitization
- SQL injection prevention
- Stateless API servers
- Distributed PubSub
- Connection pooling
- Load balancing
- Database indexing
- Query optimization
- Caching strategies
- Background job processing
- Request latency
- WebSocket connections
- Database performance
- Firebase sync latency
- Structured logging
- Error tracking
- Audit logging
- Performance logging
-
Application Errors
- Invalid input
- Authorization failures
- Resource not found
-
System Errors
- Database connection issues
- Firebase sync failures
- Network timeouts
- Automatic retries
- Circuit breakers
- Fallback mechanisms
- Data reconciliation
lib/
├── realtime_server/
│ ├── accounts/ # User management
│ ├── comments/ # Comment context
│ ├── firebase/ # Firebase integration
│ └── presence/ # Presence tracking
├── realtime_server_web/
│ ├── channels/ # WebSocket channels
│ ├── controllers/ # REST controllers
│ └── views/ # JSON views
- Unit tests
- Integration tests
- Channel tests
- Load tests
graph TD
LB[Load Balancer]
API1[API Server 1]
API2[API Server 2]
DB[(MySQL)]
FB[(Firebase)]
Cache[(Redis)]
LB --> API1
LB --> API2
API1 --> DB
API2 --> DB
API1 --> FB
API2 --> FB
API1 --> Cache
API2 --> Cache
graph TD
Client[Application]
Primary[(Primary DB)]
Replica1[(Read Replica 1)]
Replica2[(Read Replica 2)]
Client -->|Writes| Primary
Client -->|Reads| Replica1
Client -->|Reads| Replica2
Primary -->|Replication| Replica1
Primary -->|Replication| Replica2
- Write operations always go to primary
- Read operations are distributed among replicas
- Automatic fallback to primary if replicas are unavailable