Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

01 — Product Overview (WS / Realtime Module)

The realtime push layer of StudyLyon. Not a product surface by itself — it is the delivery mechanism that makes notifications, dashboards and lists live on web clients. Authoritative conventions live in 00-shared/*; module specifics here.


1. What this module is

StudyLyon's WebSocket stack delivers server-pushed domain events to authenticated clients. Two moving parts in source:

PieceSourceRole
WsGatewaysrc/modules/ws/ws.gateway.tsSocket.io gateway on namespace /ws; JWT handshake, tenant rooms, subscribe/unsubscribe
WsBridgesrc/modules/ws/ws-bridge.service.tsHooks the in-process EventBus and broadcasts every domain event to the emitting tenant
WsModulesrc/modules/ws/ws.module.tsModule wiring; registers JwtModule for handshake verification (ws.module.ts:7)

End-to-end flow, per source:

domain service → EventBus.emit()            (events/event-bus.service.ts:11)
      → WsBridge.onAny()                    (ws-bridge.service.ts:16)
      → WsGateway.broadcastToTenant()       (ws.gateway.ts:76)
      → server.to(`tenant:{id}`).emit()     → all sockets of that tenant

The blueprint defines the scope: "WebSockets under /ws for in-app notifications and live dashboards" (studylyon-blueprint/02-Architecture/API_DESIGN.md:76).

2. Scope (in / out)

In scope today

  • Authenticated connection handshake (JWT access token) — ws.gateway.ts:35-57.
  • Implicit tenant room per connection — client.join('tenant:...') (ws.gateway.ts:50).
  • Fan-out of all domain events to the tenant room — ws-bridge.service.ts:16-22.
  • Client-driven subscribe / unsubscribe to additional rooms — ws.gateway.ts:63-74.

Out of scope today (see gaps)

  • REST surface: none; this module has no HTTP endpoints (see 12_API_Mapping.md).
  • Per-user rooms, per-room RBAC, event acknowledgement, error channel, heartbeat tuning.
  • Redis pub/sub fan-out for horizontal scale — no socket.io adapter exists in src/infrastructure/redis/ (only the shared REDIS_CLIENT, redis.constants.ts:1-2).
  • Native mobile push. PRD note: the PRD scopes the product to web clients; the native app is excluded from realtime scope. Push notifications, device tokens and session join links are forward-looking (docs/IMPLEMENTATION_PLAN.md:231,769,859).

Planned consumers (per implementation plan)

  • Communication module — realtime message delivery via this WsModule (docs/IMPLEMENTATION_PLAN.md:119).
  • Transport live tracking — docs/IMPLEMENTATION_PLAN.md:229 (planned).
  • Notifications preferences/channels/device tokens — docs/IMPLEMENTATION_PLAN.md:231 (planned; WebSocket is one channel).

3. Goals

  1. Deliver domain events to the right tenant with low latency (single-hop in-process).
  2. Keep the connection layer invisible to users (reconnect handled by client + socket.io).
  3. Stay tenant-isolated: a socket may only receive events for the tenant in its JWT.
  4. Survive restarts: bridge is idempotent (onModuleInit, ws-bridge.service.ts:15).

4. Non-goals

  • Chat/messaging protocol design (Communication module owns it — planned).
  • Guaranteed at-least-once delivery / replay; events are ephemeral fire-and-forget.
  • Backfill of missed events while disconnected (clients refetch via REST — eventual consistency).

5. Success signals (proposed)

  • Connection success rate ≥ 99.5% on stable networks.
  • p95 event → client render < 1 s.
  • Zero tenant-isolation incidents.
  • 10k concurrent connections per instance load-tested (docs/IMPLEMENTATION_PLAN.md:842 — plan calls this out as a scale risk).