278 lines
11 KiB
Markdown
278 lines
11 KiB
Markdown
Perfetto Fabio — ora ti preparo il diagramma del flusso completo, chiaro, leggibile e fedele al comportamento reale del tuo sistema.
|
||
|
||
È un diagramma architetturale, non un semplice schema: mostra tutto il ciclo di vita di una sessione WebSocket affidabile, con SQLite, retry, timeout, needfullsync e sync del client.
|
||
|
||
---
|
||
|
||
🟦 DIAGRAMMA DEL FLUSSO COMPLETO — WebSocket Affidabile + Sync
|
||
|
||
Lo divido in 6 sezioni:
|
||
|
||
1. Connessione iniziale
|
||
2. Autenticazione + session_id
|
||
3. Invio evento dal server
|
||
4. Ricezione evento dal client
|
||
5. Retry + Timeout + needfullsync
|
||
6. Riconnessione del client
|
||
|
||
---
|
||
|
||
🟩 1) CONNESSIONE INIZIALE
|
||
|
||
`
|
||
CLIENT (browser) SERVER (ws-server.js)
|
||
──────────────────────────────────────────────────────────────────────
|
||
|
||
startWebSocket()
|
||
↓
|
||
Apre WebSocket ------------------------→ ws.on("connection")
|
||
crea ws object
|
||
ws.authenticated = false
|
||
`
|
||
|
||
---
|
||
|
||
🟩 2) AUTENTICAZIONE + SESSION_ID
|
||
|
||
`
|
||
CLIENT SERVER
|
||
──────────────────────────────────────────────────────────────────────
|
||
|
||
Invia:
|
||
{
|
||
type: "auth",
|
||
token: JWT,
|
||
session_id: <persistente>
|
||
}
|
||
↓ ws.on("message")
|
||
verifica JWT
|
||
cerca sessione in SQLite
|
||
se non esiste → createSession()
|
||
aggiorna last_ack
|
||
salva wsBySession[session_id] = ws
|
||
|
||
Riceve:
|
||
{
|
||
type: "auth_ok",
|
||
user: "...",
|
||
session_id: "...",
|
||
needfullsync: true/false
|
||
}
|
||
↓
|
||
Se needfullsync = true → incrementalSync()
|
||
`
|
||
|
||
---
|
||
|
||
🟩 3) INVIO EVENTO DAL SERVER (broadcast affidabile)
|
||
|
||
`
|
||
SERVER
|
||
──────────────────────────────────────────────────────────────────────
|
||
|
||
broadcastToUserReliable(user, payload)
|
||
↓
|
||
Genera event_id (UUID)
|
||
↓
|
||
Per ogni sessione dell’utente:
|
||
- Se ws attivo:
|
||
ws.send(payload + event_id)
|
||
addPendingEvent(eventid, sessionid)
|
||
- Se ws NON attivo:
|
||
setSessionNeedFullSync(session_id, true)
|
||
`
|
||
|
||
---
|
||
|
||
🟩 4) RICEZIONE EVENTO DAL CLIENT
|
||
|
||
`
|
||
CLIENT
|
||
──────────────────────────────────────────────────────────────────────
|
||
|
||
Riceve evento:
|
||
{
|
||
type: "added" | "removed" | ...,
|
||
id: "...",
|
||
event_id: "..."
|
||
}
|
||
|
||
↓
|
||
Se event_id già in processedEvents:
|
||
- invia solo ACK
|
||
- ignora evento
|
||
- FINE
|
||
|
||
Se nuovo:
|
||
- applica evento (add/remove foto)
|
||
- aggiorna UI
|
||
- aggiunge event_id a processedEvents
|
||
- invia ACK:
|
||
{ type: "ack", event_id }
|
||
`
|
||
|
||
---
|
||
|
||
🟩 5) RETRY + TIMEOUT + NEEDFULLSYNC
|
||
|
||
`
|
||
SERVER (ogni 3 secondi)
|
||
──────────────────────────────────────────────────────────────────────
|
||
|
||
Legge da SQLite tutti gli eventi pendenti
|
||
con sent_at < now - 3000 ms
|
||
|
||
Per ogni evento:
|
||
|
||
Se retries < 40 (2 minuti):
|
||
- se ws attivo:
|
||
ws.send(payload)
|
||
updatePendingEventRetry()
|
||
- se ws NON attivo:
|
||
setSessionNeedFullSync(session_id, true)
|
||
deletePendingEvent(event_id)
|
||
|
||
Se retries >= 40:
|
||
- ws.terminate()
|
||
- wsBySession.delete(session_id)
|
||
- deleteSession(session_id) ← cancella queue
|
||
- (sessione verrà ricreata al prossimo auth)
|
||
`
|
||
|
||
---
|
||
|
||
🟩 6) RICONNESSIONE DEL CLIENT
|
||
|
||
`
|
||
CLIENT riapre la tab / si risveglia
|
||
──────────────────────────────────────────────────────────────────────
|
||
|
||
startWebSocket()
|
||
↓
|
||
Invia auth con lo stesso session_id
|
||
↓
|
||
SERVER:
|
||
- trova sessione in SQLite?
|
||
NO → la ricrea con needfullsync = true
|
||
SÌ → legge needfullsync
|
||
|
||
- invia authok con needfull_sync
|
||
|
||
CLIENT:
|
||
Se needfullsync = true:
|
||
incrementalSync()
|
||
Altrimenti:
|
||
continua con WS realtime
|
||
`
|
||
|
||
---
|
||
|
||
🟦 RISULTATO DEL FLUSSO
|
||
|
||
✔ Nessun evento perso
|
||
|
||
✔ Nessun evento duplicato
|
||
|
||
✔ Chrome Android non può più “morire in silenzio”
|
||
|
||
✔ Multi‑dispositivo perfetto
|
||
|
||
✔ Queue pulita dopo 2 minuti
|
||
|
||
✔ Sync completo automatico quando serve
|
||
|
||
✔ WS leggero (ping solo on‑demand)
|
||
|
||
✔ Stato persistente in SQLite
|
||
|
||
---
|
||
|
||
|
||
┌──────────────────────────┐ ┌──────────────────────────┐
|
||
│ CLIENT │ │ SERVER │
|
||
└─────────────┬────────────┘ └─────────────┬────────────┘
|
||
│ │
|
||
│ 1) Connessione WS │
|
||
├──────────────────────────────────────→│
|
||
│ │
|
||
│ 2) AUTH + session_id │
|
||
│ {type:auth, token, session_id} │
|
||
├──────────────────────────────────────→│
|
||
│ │
|
||
│ │ verifica JWT
|
||
│ │ cerca sessione in DB
|
||
│ │ crea/aggiorna sessione
|
||
│ │
|
||
│ 3) AUTH_OK │
|
||
│ ←──────────────────────────────────────┤
|
||
│ {need_full_sync:true/false} │
|
||
│ │
|
||
│ se need_full_sync → incrementalSync() │
|
||
│ │
|
||
──────────────┼────────────────────────────────────────┼──────────────
|
||
│ │
|
||
│ 4) Ricezione evento WS │
|
||
│ {type:added/removed, event_id} │
|
||
│ ←──────────────────────────────────────┤
|
||
│ │
|
||
│ se event_id già visto → ACK │
|
||
│ se nuovo → applica evento │
|
||
│ │
|
||
│ ACK │
|
||
├──────────────────────────────────────→│
|
||
│ │
|
||
──────────────┼────────────────────────────────────────┼──────────────
|
||
│ │
|
||
│ │ 5) Retry loop (ogni 3s)
|
||
│ │ cerca eventi pendenti
|
||
│ │
|
||
│ │ se retries < 40:
|
||
│ │ reinvia evento
|
||
│ │
|
||
│ │ se retries >= 40:
|
||
│ │ ws.terminate()
|
||
│ │ deleteSession()
|
||
│ │ (queue eliminata)
|
||
│ │
|
||
──────────────┼────────────────────────────────────────┼──────────────
|
||
│ │
|
||
│ 6) Riconnessione client │
|
||
├──────────────────────────────────────→│
|
||
│ {auth, token, session_id} │
|
||
│ │
|
||
│ │ server vede sessione mancante
|
||
│ │ → need_full_sync = true
|
||
│ │
|
||
│ AUTH_OK │
|
||
│ ←──────────────────────────────────────┤
|
||
│ {need_full_sync:true} │
|
||
│ │
|
||
│ incrementalSync() │
|
||
│ │
|
||
──────────────┴────────────────────────────────────────┴──────────────
|
||
|
||
CLIENT → WS CONNECT
|
||
CLIENT → AUTH(token, session_id)
|
||
SERVER → AUTH_OK(need_full_sync)
|
||
|
||
EVENTO:
|
||
SERVER → EVENT(event_id)
|
||
CLIENT:
|
||
se nuovo → applica + ACK
|
||
se già visto → solo ACK
|
||
|
||
RETRY LOOP:
|
||
se retries < 40 → reinvia
|
||
se retries >= 40 → chiudi WS + cancella sessione
|
||
|
||
RICONNESSIONE:
|
||
CLIENT → AUTH(session_id)
|
||
SERVER → AUTH_OK(need_full_sync=true)
|
||
CLIENT → incrementalSync()
|
||
|
||
______
|
||
|
||
|
||
AUTH → EVENTI → ACK → (retry finché vivo)
|
||
se client sparisce → timeout → cancella sessione
|
||
se torna → need_full_sync → incrementalSync
|