1
0
peddlers-of-ketran/ARCHITECTURE_DIAGRAM.md

354 lines
19 KiB
Markdown

# Architecture Diagram
## System Overview
```
┌────────────────────────────────────────────────────────────────┐
│ CLIENT APPLICATIONS │
│ │
│ ┌───────────────────┐ ┌───────────────────┐ │
│ │ Settlers Game │ │ Chat Room App │ │
│ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │
│ │ │ Game UI │ │ │ │ Chat UI │ │ │
│ │ │ - Board │ │ │ │ - Messages │ │ │
│ │ │ - Actions │ │ │ │ - Input │ │ │
│ │ └─────────────┘ │ │ └─────────────┘ │ │
│ │ │ │ │ │
│ │ Uses: │ │ Uses: │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ REUSABLE COMPONENTS │ │ │
│ │ │ • MediaControl (Video/Audio UI) │ │ │
│ │ │ • MediaAgent (WebRTC Signaling) │ │ │
│ │ │ • PlayerList (Participant Display) │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ └───────────────────┘ └───────────────────┘ │
└────────────────────────────────────────────────────────────────┘
│ WebSocket
┌────────────────────────────────────────────────────────────────┐
│ SERVER LAYERS │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ APPLICATION LAYER (App-Specific) │ │
│ │ │ │
│ │ Settlers Game │ Chat App │ │
│ │ ┌────────────────────┐ │ ┌───────────────────┐ │ │
│ │ │ GameSessionMeta │ │ │ ChatSessionMeta │ │ │
│ │ │ - color │ │ │ - status │ │ │
│ │ │ - player │ │ │ - messageCount │ │ │
│ │ │ - resources │ │ │ - customStatus │ │ │
│ │ └────────────────────┘ │ └───────────────────┘ │ │
│ │ │ │ │
│ │ ┌────────────────────┐ │ ┌───────────────────┐ │ │
│ │ │ GameRoomMeta │ │ │ ChatRoomMeta │ │ │
│ │ │ - players │ │ │ - messages │ │ │
│ │ │ - board setup │ │ │ - topic │ │ │
│ │ │ - game rules │ │ │ - pinnedMessages │ │ │
│ │ └────────────────────┘ │ └───────────────────┘ │ │
│ │ │ │
│ │ Message Handlers: │ Message Handlers: │ │
│ │ • set color │ • send message │ │
│ │ • place settlement │ • set status │ │
│ │ • trade resources │ • pin message │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ │ uses metadata │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ ADAPTER LAYER (Optional Compatibility) │ │
│ │ │ │
│ │ Proxy Handlers: │ │
│ │ • session.color ─────→ session.metadata.color │ │
│ │ • session.player ────→ session.metadata.player │ │
│ │ • game.players ──────→ game.metadata.players │ │
│ │ │ │
│ │ Enables backward compatibility without code changes │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ │ wraps │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ INFRASTRUCTURE LAYER (Reusable Framework) │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ Session Management │ │ │
│ │ │ • BaseSession (id, name, ws, live, has_media) │ │ │
│ │ │ • Session<TMeta> (+ metadata field) │ │ │
│ │ │ • createBaseSession() │ │ │
│ │ │ • updateSessionActivity() │ │ │
│ │ │ • isSessionActive() │ │ │
│ │ │ • getSessionName() │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ Room Management │ │ │
│ │ │ • BaseRoom (id, name, sessions, state) │ │ │
│ │ │ • Room<TMeta> (+ metadata field) │ │ │
│ │ │ • getParticipants() │ │ │
│ │ │ • getActiveSessions() │ │ │
│ │ │ • cleanupInactiveSessions() │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ WebRTC Signaling │ │ │
│ │ │ • join() - Add peer to registry │ │ │
│ │ │ • part() - Remove peer from registry │ │ │
│ │ │ • relayICECandidate() - Forward ICE │ │ │
│ │ │ • relaySessionDescription() - Forward SDP │ │ │
│ │ │ • PeerRegistry - Track peer connections │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ WebSocket Handling │ │ │
│ │ │ • Connection management │ │ │
│ │ │ • Automatic reconnection │ │ │
│ │ │ • Message routing │ │ │
│ │ │ • Keep-alive pings │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
```
## Data Flow: Setting User Name
```
┌─────────────┐
│ CLIENT │
└─────────────┘
│ 1. User types name "Alice"
sendJsonMessage({
type: "set",
field: "name",
value: "Alice"
})
│ WebSocket
┌─────────────────────────────────────────┐
│ SERVER │
│ │
│ Infrastructure Layer: │
│ ├─ Receive message │
│ ├─ Find session by WebSocket │
│ └─ Route to handler │
│ │
│ Application Layer: │
│ ├─ session.name = "Alice" │
│ └─ Broadcast to all sessions │
│ │
│ Infrastructure Layer: │
│ └─ getParticipants(room.sessions) │
│ └─ Returns: [ │
│ { session_id, name: "Alice", │
│ live: true, has_media: true } │
│ ] │
└─────────────────────────────────────────┘
│ Broadcast update
┌─────────────┐
│ ALL CLIENTS│
└─────────────┘
│ Receive participants update
PlayerList rerenders
with "Alice" shown
```
## Data Flow: Joining Video Call
```
┌─────────────┐
│ CLIENT │
└─────────────┘
│ 1. MediaAgent mounts
│ 2. Gets user media (camera/mic)
sendJsonMessage({
type: "join",
data: { has_media: true }
})
│ WebSocket
┌──────────────────────────────────────────┐
│ SERVER │
│ │
│ Infrastructure Layer (WebRTC): │
│ ├─ join(peers, session, { has_media }) │
│ │ │
│ │ For each existing peer: │
│ │ ├─ Send addPeer to existing peer │
│ │ │ { peer_id: "Alice", │
│ │ │ peer_name: "Alice", │
│ │ │ has_media: true, │
│ │ │ should_create_offer: false } │
│ │ │ │
│ │ └─ Send addPeer to new peer │
│ │ { peer_id: "Bob", │
│ │ peer_name: "Bob", │
│ │ has_media: true, │
│ │ should_create_offer: true } │
│ │ │
│ └─ Add to peer registry: │
│ peers["Alice"] = { │
│ ws, has_media: true │
│ } │
│ │
│ └─ Send join_status: │
│ { type: "join_status", │
│ status: "Joined" } │
└──────────────────────────────────────────┘
│ Relay messages
┌─────────────┐
│ ALL CLIENTS│
└─────────────┘
│ Each client:
├─ Creates RTCPeerConnection
├─ Adds local media tracks
├─ Creates offer/answer
└─ Exchanges ICE candidates
Peer-to-peer video/audio flows
```
## Data Flow: Game-Specific Action
```
┌─────────────┐
│ GAME CLIENT│
└─────────────┘
│ Player clicks "Blue" color
sendJsonMessage({
type: "set",
field: "color",
value: "blue"
})
│ WebSocket
┌───────────────────────────────────────────┐
│ SERVER │
│ │
│ Infrastructure Layer: │
│ ├─ Route message to app handler │
│ └─ session object available │
│ │
│ Adapter Layer (optional): │
│ └─ Wraps session with proxy │
│ │
│ Application Layer (Game): │
│ ├─ setPlayerColor(game, session, "blue")│
│ │ ├─ Validate color available │
│ │ ├─ session.color = "blue" │ ← Direct access
│ │ │ (or session.metadata.color) │ ← New arch
│ │ ├─ session.player = gamePlayer │
│ │ └─ Update game.metadata.players │
│ │ │
│ └─ Broadcast update: │
│ participants: [ │
│ { │
│ ...baseParticipant, │ ← Infrastructure
│ color: "blue" │ ← App-specific
│ } │
│ ] │
└───────────────────────────────────────────┘
│ Broadcast
┌─────────────┐
│ ALL CLIENTS│
└─────────────┘
│ Update UI
PlayerList shows
"Alice" with blue color
```
## Metadata Access Patterns
### Without Adapter (New Code)
```typescript
// Explicit metadata access
const color = session.metadata?.color;
session.metadata = { ...session.metadata, color: 'blue' };
const players = room.metadata.players;
room.metadata.players['blue'] = newPlayer;
```
### With Adapter (Backward Compatible)
```typescript
// Same as before - adapter proxies to metadata
const color = session.color;
session.color = 'blue';
const players = room.players;
room.players['blue'] = newPlayer;
```
Both work! Adapter allows gradual migration.
## Reusability Layers
```
Application A (Settlers) Application B (Chat) Application C (Whiteboard)
│ │ │
├── GameSessionMeta ├── ChatSessionMeta ├── WhiteboardSessionMeta
│ - color │ - status │ - cursorColor
│ - player │ - messageCount │ - selectedTool
│ │ │
└─────────────┬────────────┴────────────────────────┘
│ All apps extend base types
┌─────────────────────────────────┐
│ INFRASTRUCTURE (Shared) │
│ • Session<TMeta> │
│ • Room<TMeta> │
│ • MediaControl (WebRTC) │
│ • getParticipants() │
│ • Session management │
└─────────────────────────────────┘
Single implementation,
works for all apps!
```
## Summary
This architecture provides:
**Clean separation** between infrastructure and application
**Type-safe metadata** for app-specific data
**Reusable components** that work across applications
**Backward compatibility** via adapter layer
**Clear data flows** from client to server to all clients
**Proven patterns** ready for production use
Any new application can plug into the infrastructure and get:
- Multi-user rooms
- WebSocket connection management
- WebRTC video/audio signaling
- Participant tracking
- UI components (MediaControl)
All for free! Just define your metadata types and business logic.