# 🛰️ Real-Time Communication Guide

A comprehensive, end-to-end reference for the Household Management App's WebSocket infrastructure.

---

## 1. High-Level Overview

| Layer | Purpose |
|-------|---------|
| **Backend** | Broadcasts domain events (chores, groups, items, expenses…) to targeted rooms with optional user exclusion. |
| **Frontend** | Maintains a single authenticated WebSocket connection per household, routes incoming events to Pinia stores, updates UI & triggers notifications. |

All events share a **type-safe JSON contract**:

```jsonc
{
  "event": "chore:updated",   // namespaced event key (domain:action)
  "payload": { /* entity-specific */ },
  "timestamp": "2025-06-29T12:34:56Z",
  "user_id": 42,               // originating user (optional)
  "room": "household:7"       // broadcast room (optional)
}
```

---

## 2. Backend Architecture

### 2.1 Entry Point

```mermaid
sequenceDiagram
    participant Client
    participant FastAPI as FastAPI /api/v1/ws/household/{id}
    participant Manager as WebSocketManager (core/websocket.py)
    Client->>FastAPI: WebSocket handshake (token query param)
    FastAPI->>Manager: register(socket, household_id, user)
    Manager-->>Client: connection:established
```

* **Endpoint**: `be/app/api/v1/endpoints/websocket.py`
* **Authentication**: JWT access token retrieved from query string and validated via FastAPI dependency.
* **Manager (`core/websocket.py`)**
  * Keeps `Dict[str, Set[WebSocket]]` mapping of **rooms** ➜ sockets.
  * Offers helpers:`broadcast(room, event, payload, *, exclude_user_id=None)`.
  * Auto-removes closed connections & handles ping/pong.

### 2.2 Room Conventions

| Room | Used For | Example |
|------|----------|---------|
| `household:{id}` | Global events within a household | `household:7` |
| `list:{id}` | Shopping list specific events | `list:12` |
| `expense:{id}` | Expense settlement events | `expense:88` |

### 2.3 Event Producers

| Module | Function(s) | Emitted Events |
|--------|-------------|---------------|
| `crud/chore.py` | `create_chore`, `update_chore`, `delete_chore`, … | `chore:created`, `chore:updated`, `chore:deleted`, `chore:assigned`, `chore:completed`, `chore:assignment_updated` |
| `crud/group.py` | `create_group`, `add_user_to_group`, `remove_user_from_group`, `delete_group` | `group:created`, `group:member_joined`, `group:member_left`, `group:deleted` |
| `crud/invite.py` | `create_invite`, `deactivate_invite` | `group:invite_created`, `group:invite_used` |
| `crud/item.py` | `create_item`, `update_item`, `delete_item`, `claim_item`, `unclaim_item` | `item:created`, `item:updated`, `item:deleted`, `item:claimed`, `item:unclaimed` |
| `crud/expense.py` | `create_expense`, `update_expense`, `delete_expense` | `expense:created`, `expense:updated`, `expense:deleted` |

> **Smart User Exclusion**: Every helper call passes the acting `user_id`; the manager omits that socket to prevent "echo" effects on the originator.

### 2.4 Reliability & Performance

* **Graceful Degradation** – Exceptions in broadcasting are caught; CRUD logic always completes.
* **Ping / Pong** – Server sends `ping` every **25 s**; client replies with `pong`.
* **Scalability** – Manager is stateless apart from room maps and can be swapped for Redis-backed pub/sub later.

---

## 3. Frontend Architecture

### 3.1 useSocket Composable

Located at `fe/src/composables/useSocket.ts`.

* **Single Source of Truth** – Global reactive state (`socket`, `listeners`, `isConnected`…).
* **Connection Logic**
  * URL: `ws(s)://{host}/api/v1/ws/household/{householdId}?token=JWT`.
  * Exponential reconnect (1 s → 2 s → 4 s → …, max 5 attempts).
  * Heartbeat every **30 s** (`presence_update: heartbeat`).
* **Event Routing**
  * `listeners: Map<string, Set<Function>>` – any store/component registers via `on(event, cb)`.
  * Raw server `ping` handled automatically.
* **Outgoing Convenience**
  * `emit(event, payload)` – client-side custom events (rarely used).
  * `startEditing/stopEditing`, `updatePresence` helpers.

### 3.2 Pinia Store Integration

| Store | Event Handlers | Highlights |
|-------|----------------|-----------|
| **choreStore** | `chore:*`, `timer:*` | Updates local arrays & triggers assignment/completion notifications. |
| **groupStore** | `group:*`, `invite:*` | Live member joins/leaves, group CRUD & smart redirection. |
| **itemStore** | `item:*` | Real-time shopping list sync with claim/unclaim notifications. |
| **listDetailStore** | `list:updated`, `expense:*` | Keeps list view & expenses fresh during collaboration. |

All stores follow a **canonical pattern**:

```ts
function setupWebSocketListeners() {
  on('entity:created', handleCreated)
  on('entity:updated', handleUpdated)
  // ...
}

function cleanupWebSocketListeners() {
  off('entity:created', handleCreated)
  // ...
}
```

### 3.3 Notification Strategy

`fe/src/stores/notifications.ts` provides a lightweight queue. Stores push human-friendly messages:

* Self-actions filtered (`user_id !== currentUser.id`).
* Importance-based durations (info 3 s, success 5 s, errors manual close).
* Display component: `components/global/NotificationDisplay.vue`.

### 3.4 Presence & Editing (Future)

API scaffolding exists (`startEditing`, `presence_update`). UI indicators will be added in the next milestone.

---

## 4. Event Reference (Cheat-Sheet)

| Domain | Event | Payload Shape |
|--------|-------|---------------|
| **Chores** | `chore:created` | `{ chore: Chore }` |
| | `chore:updated` | `{ chore: Chore }` |
| | `chore:deleted` | `{ choreId: number, groupId? }` |
| | `chore:assigned` / `chore:assignment_updated` | `{ assignment: ChoreAssignment }` |
| | `chore:completed` | `{ assignment: ChoreAssignment, points: number }` |
| **Groups** | `group:created` | `{ group: GroupPublic }` |
| | `group:member_joined` / `member_left` | `{ groupId: number, member / userId }` |
| | `group:deleted` | `{ groupId: number }` |
| **Invites** | `group:invite_created` / `invite_used` | `{ groupId: number, invite… }` |
| **Items** | `item:*` | Item entity specific |
| **Lists** | `list:updated` | `{ list: List }` |
| **Expenses** | `expense:*` | Expense entity specific |

---

## 5. Adding a New Real-Time Feature

1. **Backend** – Identify CRUD mutation ➜ call `broadcast_event()` with new `event` key.
2. **Frontend** – In relevant Pinia store:
   * import `useSocket`,
   * register `on('new:event', handler)` in `setupWebSocketListeners()`.
3. **UI / Notifications** – Optionally surface via component or toast.
4. **Docs** – Append to the table above.

---

## 6. Troubleshooting & Tips

| Symptom | Likely Cause | Fix |
|---------|--------------|-----|
| No connection | Invalid JWT / expired | Refresh token & reconnect. |
| Echo events | Backend `exclude_user_id` missing | Pass `current_user.id` to broadcast helper. |
| Stale UI after reconnect | Stores lost listeners on HMR | Call `setupWebSocketListeners()` in Pinia definition (runs once). |
| High CPU on server | Broadcast loops | Ensure room targeting is specific (e.g., list-level not household-level for item events). |

---

## 7. Roadmap

* Presence indicators per list/chore (avatars + typing)…
* Redis-based pub/sub for horizontal scaling.
* WebSocket analytics dashboard (latency, event throughput).

---

> **Last updated**: 2025-06-29   |
> **Author**: Engineering Team
