photo_server_json_con_aves22/README_WS.md
2026-04-18 20:14:42 +02:00

278 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 dellutente:
- 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”
✔ Multidispositivo perfetto
✔ Queue pulita dopo 2 minuti
✔ Sync completo automatico quando serve
✔ WS leggero (ping solo ondemand)
✔ 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