docs: add comprehensive technical wiki documentation and flaws analysis; remove legacy BRAIN.md
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 8s
This commit is contained in:
1 parent
10d5c6d563
commit
3480859d8a
13 files changed
+1577
-317
No files matched your search
@@ -0,0 +1,113 @@
|
||||
# 📡 WebSocket & Echtzeit-Synchronisation
|
||||
|
||||
MindSift implementiert eine bidirektionale Echtzeit-Synchronisationsschicht auf Basis von WebSockets ([`internal/ws/hub.go`](../../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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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**:
|
||||
|
||||
```mermaid
|
||||
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`](../../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.
|
||||
Reference in new issue
Block a user