Files
MindSift/Doku/api/websocket.md
T
sandrodach 3480859d8a
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
docs: add comprehensive technical wiki documentation and flaws analysis; remove legacy BRAIN.md
2026-10-26 13:27:35 +01:00

5.5 KiB

📡 WebSocket & Echtzeit-Synchronisation

MindSift implementiert eine bidirektionale Echtzeit-Synchronisationsschicht auf Basis von WebSockets (internal/ws/hub.go). Sie sorgt dafür, dass Änderungen an Aufgaben, Triage-Karten, Notizen und geteilten Einkaufslisten ohne manuelles Neuladen sofort auf allen geöffneten Geräten und bei allen Kollaborationspartnern sichtbar werden.


🔌 1. Verbindung & Handshake

Verbindungs-Endpunkte

wss://<domain>/api/v1/ws?token=<jwt-token>
wss://<domain>/api/v1/ws/lists/<listId>?token=<jwt-token>

Authentifizierung & Upgrade

  • Die Authentifizierung erfolgt über das JWT-Token im Query-Parameter ?token=... oder den Authorization: Bearer-Header während des HTTP-Upgrade-Requests.
  • Der Server extrahiert die userID und registriert die Verbindung im internen Hub.
  • Der Upgrader akzeptiert alle Origins (CheckOrigin: return true), um volle Kompatibilität mit Reverse-Proxies (Traefik, Nginx, Caddy, Cloudflare) und Docker-Netzwerken zu gewährleisten.

🏛️ 2. Hub-Architektur & Rooms

Der WebSocket-Hub unterteilt Verbindungen in drei Abstraktionsebenen:

┌─────────────────────────────────────────────────────────────────┐
│                           WebSocket Hub                         │
├─────────────────┬─────────────────────────────┬─────────────────┤
│   allClients    │          userRooms          │      rooms      │
│  (Alle aktiven  │     (Pro Benutzer-ID)       │   (Pro Liste/   │
│   Verbindungen) │  Cross-Device Sync für      │     Space)      │
│                 │  Tasks, Triage & Workspace  │  Geteilte Liste │
└────────┬────────┴──────────────┬──────────────┴────────┬────────┘
         ▼                       ▼                       ▼
   Presence Stats          TASK_CREATED             ITEM_TOGGLED
   DOC_LOCKED              TASK_UPDATED             ITEM_CREATED
   DOC_UNLOCKED            DOC_UPDATED              LIST_UPDATED
  1. allClients (Global): Hält jede aktive Client-Verbindung. Ermöglicht Broadcasts systemweiter Ereignisse (z.B. globale Dokument-Sperrungen).
  2. userRooms[userID] (Benutzer-Räume): Sendet Events an alle Geräte desselben Benutzers (z.B. Desktop und Smartphone). Erzeugt ein Webhook oder Quick Dump auf dem Smartphone einen Eintrag, taucht dieser zeitgleich auf dem Desktop auf.
  3. rooms[listID] (Kollaborations-Räume): Multiplexing für geteilte Listen. Alle Mitglieder einer Liste empfangen Aktionen (wie Abhaken, Löschen, Umsortieren) in Echtzeit.

📨 3. Nachrichten-Format (Envelope)

Alle WebSocket-Nachrichten werden als JSON mit einheitlicher Hülle übertragen:

{
  "event": "ITEM_TOGGLED",
  "listId": "lst_12345",
  "payload": {
    "itemId": "itm_987",
    "isCompleted": true,
    "completedBy": "usr_sandro",
    "completedByName": "Sandro"
  },
  "timestamp": "2026-10-26T13:30:00Z"
}

🔒 4. Dokument-Sperrsystem (Document Locking)

Um Schreibkonflikte bei Notizen im Workspace zu vermeiden, verwendet MindSift ein serverseitiges Lease-Locking mit Heartbeat:

sequenceDiagram
    autonumber
    actor UserA as Benutzer A
    participant WS as WebSocket Hub
    actor UserB as Benutzer B

    UserA->>WS: LOCK_DOC (docId: "doc_123")
    WS-->>UserA: Lock bestätigt (30s TTL)
    WS->>UserB: DOC_LOCKED (docId: "doc_123", lockedBy: "Benutzer A")
    Note over UserB: Editor gesperrt (Schreibschutz aktiv)

    loop Alle 15 Sekunden
        UserA->>WS: HEARTBEAT_DOC (docId: "doc_123")
        WS-->>UserA: TTL um 30s verlängert
    end

    alt Reguläres Schließen
        UserA->>WS: UNLOCK_DOC (docId: "doc_123")
        WS->>UserB: DOC_UNLOCKED (docId: "doc_123")
        Note over UserB: Editor wieder freigegeben
    else Verbindungsabbruch / Tab geschlossen
        Note over WS: Heartbeat bleibt aus (TTL läuft ab)
        WS->>UserB: DOC_UNLOCKED (Automatisch nach Ablauf)
    end

Locking-Events

  • LOCK_DOC (Client ➔ Server): Fordert eine 30-Sekunden-Sperre für ein Dokument an.
  • HEARTBEAT_DOC (Client ➔ Server): Verlängert die Sperre alle 15 Sekunden, solange der Benutzer das Dokument geöffnet hat.
  • UNLOCK_DOC (Client ➔ Server): Gibt die Sperre beim Verlassen des Dokuments frei.
  • DOC_LOCKED (Server ➔ Clients): Informiert andere Benutzer, dass das Dokument schreibgeschützt ist.
  • DOC_UNLOCKED (Server ➔ Clients): Hebt den Schreibschutz auf.

🔄 5. Fallback-Strategie & Reconnect

In strikten Firmennetzwerken oder bei Proxy-Problemen (z.B. fehlende Upgrade-Header bei HTTP/1.1) kann eine WebSocket-Verbindung fehlschlagen:

  1. Exponentielles Backoff: Das Frontend (frontend/src/lib/api.ts) versucht automatisch die Wiederverbindung nach 1s, 2s, 4s, 8s, bis maximal 30s.
  2. HTTP-Polling Fallback: Geteilte Listen und Notizen aktivieren im Hintergrund ein periodisches Polling (5s Intervall), falls der WebSocket-Status nicht CONNECTED ist.
  3. Status-Indikator: Ein dezenter grüner bzw. gelber Indikator oben rechts im Header zeigt dem Benutzer jederzeit den aktuellen Live-Verbindungsstatus an.