Skip to content

Latest commit

 

History

History
435 lines (370 loc) · 12.3 KB

File metadata and controls

435 lines (370 loc) · 12.3 KB

Architecture Documentation

Overview

Live Loop is a modern video calling application built with a microservices-inspired architecture. The system uses WebRTC for peer-to-peer video communication, Socket.io for real-time signaling, and Redis for scalable user queue management.

System Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Web Browser   │    │   Web Browser   │    │   Web Browser   │
│   (Client A)    │    │   (Client B)    │    │   (Client C)    │
└─────────┬───────┘    └─────────┬───────┘    └─────────┬───────┘
          │                      │                      │
          │ Socket.io            │ Socket.io            │ Socket.io
          │                      │                      │
    ┌─────▼──────────────────────▼──────────────────────▼─────┐
    │                Load Balancer                            │
    └─────┬───────────────────────────────────────────────────┘
          │
    ┌─────▼─────┐    ┌─────────────┐    ┌─────────────┐
    │  Server   │    │   Server    │    │   Server    │
    │Instance 1 │    │ Instance 2  │    │ Instance N  │
    └─────┬─────┘    └─────┬───────┘    └─────┬───────┘
          │                │                  │
          └────────────────┼──────────────────┘
                           │
                    ┌──────▼──────┐
                    │    Redis    │
                    │   Cluster   │
                    └─────────────┘

Core Components

1. Frontend Architecture

Component Hierarchy

App.jsx
├── NavbarHome.jsx
├── Router Outlet
│   ├── Home.jsx
│   │   ├── HomePageHome.jsx
│   │   ├── SetUpSection.jsx
│   │   └── ContactUsHome.jsx
│   ├── Studio.jsx
│   │   └── StudioHome.jsx
│   └── Call.jsx
│       └── CallPageHome.jsx
│           ├── ChatSection.jsx
│           └── MenuSidebar.jsx
└── Footer.jsx

State Management

// Context Providers
SocketContext (Socket.io connection)
├── StreamContext (Media streams & device management)
    └── Application Components

Data Flow

User Action → Component State → Context Update → Socket Emission → Server Processing → Socket Event → Context Update → Component Re-render

2. Backend Architecture

Service Layer

├── UserService (User management & matchmaking)
├── RoomService (Room creation & management)
├── RedisService (Data persistence & queuing)
└── Event Handlers (Socket.io event processing)

Event Flow

Socket Event → Event Handler → Service Layer → Data Layer → Response/Broadcast

3. Real-time Communication

WebRTC Connection Flow

User A                    Server                    User B
  │                         │                         │
  ├─ request-room ─────────▶│                         │
  │                         ├─ Add to queue          │
  │                         │                         │
  │                         │◀─ request-room ─────────┤
  │                         ├─ Match users           │
  │                         │                         │
  │◀─ match-done ───────────┤─────── match-done ────▶│
  │                         │                         │
  ├─ create offer ──────────▶│                         │
  │                         ├─ forward offer ────────▶│
  │                         │                         │
  │                         │◀─ create answer ───────┤
  │◀─ receive answer ───────┤                         │
  │                         │                         │
  ├─ ICE candidates ────────▶│─ forward candidates ──▶│
  │◀─ ICE candidates ───────┤◀─ ICE candidates ──────┤
  │                         │                         │
  │◀──── P2P Connection ─────────────────────────────▶│

Socket.io Event Architecture

Events/
├── matchmaking.ts
│   ├── request-room
│   ├── stop-call
│   └── disconnect
├── signaling.ts
│   ├── negotiation-call-offer
│   ├── negotiation-call-answer
│   └── send-new-ice-candidates
└── chatEvents.ts
    └── newMessage

Data Models

User Interface

interface User {
  socket: string;           // Socket ID
  userName: string;         // Display name
  userImage?: string;       // Base64 thumbnail
  joinedAt: Date;          // Queue join time
}

Room Interface

interface Room {
  id: string;              // Unique room identifier
  user1: User;             // First user
  user2: User;             // Second user
  createdAt: Date;         // Room creation time
  status: 'active' | 'ended';
}

Message Interface

interface ChatMessage {
  from: string;            // Sender socket ID
  message: string;         // Message content
  timestamp: Date;         // Send time
  roomId: string;         // Room identifier
}

Database Design

Redis Data Structure

Keys:
├── queue:users              # Sorted set of waiting users
├── rooms:{roomId}           # Hash of room details
├── user:{socketId}          # Hash of user information
└── metrics:daily           # Application metrics

Data Storage Patterns

// User Queue (Sorted Set)
ZADD queue:users timestamp socketId

// Room Storage (Hash)
HSET rooms:room123 user1 "socketId1" user2 "socketId2" created "timestamp"

// User Data (Hash)
HSET user:socket123 name "John" image "base64..." joined "timestamp"

Security Architecture

Authentication & Authorization

Client Request → CORS Validation → Rate Limiting → Event Processing

Data Validation

// Input validation middleware
const validateMessage = (data) => {
  if (!data.message || data.message.length > 1000) {
    throw new Error('Invalid message');
  }
};

Security Layers

  1. CORS Configuration: Restrict allowed origins
  2. Rate Limiting: Prevent abuse
  3. Input Validation: Sanitize user data
  4. Error Handling: Prevent information leakage

Performance Considerations

Frontend Optimization

// Code splitting
const CallPage = lazy(() => import('./pages/Call'));

// Memoization
const MemoizedChatMessage = memo(ChatMessage);

// Efficient re-renders
const { userName, isConnected } = useStreamContext();

Backend Optimization

// Connection pooling
const redis = new Redis({
  maxRetriesPerRequest: 3,
  lazyConnect: true
});

// Event batching
const batchEvents = (events) => {
  // Process multiple events together
};

WebRTC Optimization

// ICE candidate optimization
const pcConfig = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    { urls: 'stun:stun.l.google.com:19301' }
  ],
  iceCandidatePoolSize: 10
};

Scalability Design

Horizontal Scaling

Load Balancer
├── App Server 1 (Socket.io)
├── App Server 2 (Socket.io)
└── App Server N (Socket.io)
     │
     └── Shared Redis Cluster

Load Balancing Strategy

// Sticky sessions for Socket.io
const io = new Server(server, {
  adapter: require('@socket.io/redis-adapter')(redisClient)
});

Database Scaling

Redis Cluster
├── Master Node 1 (Read/Write)
├── Master Node 2 (Read/Write)
└── Master Node 3 (Read/Write)
   │
   ├── Slave Node 1 (Read)
   ├── Slave Node 2 (Read)
   └── Slave Node 3 (Read)

Monitoring & Observability

Application Metrics

// Custom metrics
const metrics = {
  activeConnections: 0,
  roomsCreated: 0,
  messagesExchanged: 0,
  connectionFailures: 0
};

Logging Strategy

// Structured logging
const logger = winston.createLogger({
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: 'app.log' })
  ]
});

Health Checks

// Health endpoint
app.get('/health', (req, res) => {
  res.json({
    status: 'healthy',
    timestamp: new Date().toISOString(),
    services: {
      redis: redisClient.status,
      memory: process.memoryUsage()
    }
  });
});

Error Handling

Error Categories

1. Network Errors (Connection timeouts)
2. WebRTC Errors (ICE failures)
3. Validation Errors (Invalid input)
4. System Errors (Redis unavailable)

Error Handling Strategy

// Centralized error handling
const errorHandler = (error, context) => {
  logger.error('Error occurred', { error, context });
  
  if (error.type === 'NETWORK_ERROR') {
    // Retry logic
  } else if (error.type === 'VALIDATION_ERROR') {
    // User notification
  }
};

API Design

RESTful Endpoints

GET  /                    # Health check
GET  /api/status         # System status
POST /api/rooms          # Create room (if needed)

Socket.io Events

// Namespaced events
/matchmaking
├── request-room
└── stop-call

/signaling
├── negotiation-call-offer
├── negotiation-call-answer
└── send-new-ice-candidates

/chat
└── newMessage

Development Workflow

Code Organization

Feature-based structure:
├── components/feature/
├── services/feature/
├── utils/feature/
└── types/feature/

Testing Strategy

Unit Tests (70%)
├── Service layer testing
├── Utility function testing
└── Component testing

Integration Tests (20%)
├── API endpoint testing
├── Socket.io event testing
└── Database integration testing

E2E Tests (10%)
├── User flow testing
├── WebRTC connection testing
└── Cross-browser testing

Deployment Architecture

Development Environment

Developer Machine
├── Frontend (Vite dev server)
├── Backend (Node.js with nodemon)
└── Redis (Local instance)

Production Environment

CDN (Frontend assets)
├── Load Balancer
    ├── App Server Cluster
    ├── Redis Cluster
    └── Monitoring Stack

CI/CD Pipeline

Code Push → Tests → Build → Deploy → Health Check → Release

Future Considerations

Planned Enhancements

  1. Video Recording: Store call recordings
  2. Screen Sharing: WebRTC screen capture
  3. Group Calls: Multi-user video calls
  4. Mobile App: React Native implementation
  5. Analytics: User behavior tracking

Technical Debt

  1. Test Coverage: Increase to 90%+
  2. Type Safety: Full TypeScript migration
  3. Performance: Bundle size optimization
  4. Documentation: API documentation automation

This architecture supports the current feature set while providing flexibility for future enhancements and scale.