18 KiB
Perfetto Fabio, ora che il server è sistemato posso spiegarti esattamente come funziona lo scan adesso, in modo chiaro, ordinato e soprattutto vero rispetto al codice che hai.
Ti faccio una spiegazione operativa, come se stessi guardando il flusso in tempo reale.
🔵 1. L’utente chiama /scan
Quando fai:
GET /scan
succede questo:
✔ Il middleware JWT autentica l’utente
✔ Il middleware GET non aggiunge più “Common”
→ quindi lo scan viene fatto solo per l’utente reale
→ niente doppie scansioni
→ niente doppio removed
🔵 2. Il server chiama scanPhotosUser(userName, db)
Esempio:
scanPhotosUser("Fabio", db)
Questa funzione fa due passaggi:
🟣 PASSAGGIO 1 — Conta i file reali (ricorsivo)
countFilesUser():
- entra in
/photos/Fabio/original - scende in tutte le sottocartelle
- conta solo i file con estensioni supportate
- NON tocca il DB
- NON scansiona due volte
- NON elimina orfani
Questo serve solo per:
- mostrare il progresso
- calcolare la percentuale
- stimare il tempo
E ora funziona correttamente.
🟣 PASSAGGIO 2 — Scansiona ogni cartella UNA sola volta
Per ogni cartella dentro:
/photos/Fabio/original/
viene chiamato:
scanPhoto(cartella, userName, db, ...)
🔵 3. scanPhoto() chiama scanPhotoCartella() UNA sola volta
E qui avviene la vera magia.
🟣 Dentro scanPhotoCartella() succede questo:
1️⃣ Recupera dal DB tutti gli ID della cartella
→ costruisce idsSet
2️⃣ Scansiona i file reali con scanCartella()
→ per ogni file trovato:
- aggiorna il progresso
- chiama
scanPhotoSingle()per processarlo - elimina l’ID da
idsSet(non è orfano)
3️⃣ Alla fine, gli ID rimasti in idsSet sono orfani veri
4️⃣ Per ogni orfano:
- elimina thumbs
- elimina dal DB
- registra 1 solo removed
🔥 Perché ora NON hai più 2 removed?
Perché:
/scanviene chiamato una sola voltascanPhotosUserviene eseguito una sola voltascanPhotoviene eseguito una sola voltascanPhotoCartellaviene eseguito una sola volta- gli orfani vengono eliminati una sola volta
Prima invece:
- il middleware GET aggiungeva Common
- quindi
/scanscansionava Fabio + Common - Common vedeva gli ID di Fabio come orfani
→ removed - Fabio vedeva gli ID come orfani
→ removed - totale: 2 removed
Ora questo non succede più.
🟢 RISULTATO FINALE DEL NUOVO SISTEMA
✔ 1 added quando aggiungi una foto
✔ 1 removed quando la togli
✔ nessun doppio evento
✔ nessuna doppia scansione
✔ conteggio file corretto
✔ comportamento stabile e identico al vecchio sistema
Perfetto Fabio — ti preparo un diagramma chiaro, leggibile e fedele al comportamento reale del tuo sistema, così puoi vedere tutto il flusso in un colpo d’occhio.
Lo faccio in stile flowchart testuale, così puoi anche stamparlo o incollarlo nei tuoi appunti.
🔵 DIAGRAMMA COMPLETO DELLO SCAN (versione attuale, corretta)
┌──────────────────────────────┐
│ CLIENT /scan │
└───────────────┬──────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 1. Middleware JWT │
│ ✔ Autentica l’utente │
│ ✔ Imposta req.user │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 2. Middleware GET (PATCH) │
│ ✔ NON aggiunge più "Common" │
│ ✔ Per /scan → req.query.user = [utente] │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 3. Route /scan │
│ chiama: scanPhotosUser(req.user.name, db) │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 4. scanPhotosUser(user) │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 4.1 PRIMA PASSATA (ricorsiva) │ │
│ │ countFilesUser() │ │
│ │ ✔ entra in tutte le sottocartelle│ │
│ │ ✔ conta SOLO i file supportati │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 4.2 SECONDA PASSATA │ │
│ │ per ogni cartella in /original │ │
│ │ → scanPhoto(cartella) │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 5. scanPhoto(cartella) │
│ chiama: scanPhotoCartella() │
│ (UNA sola volta per cartella) │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 6. scanPhotoCartella() │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 6.1 Recupera ID dal DB │ │
│ │ → idsSet = { id1, id2, ... } │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 6.2 Scansione reale dei file │ │
│ │ for await (f of scanCartella) │ │
│ │ → scanPhotoSingle(f) │ │
│ │ → idsSet.delete(f.id) │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 6.3 ORFANI (alla fine) │ │
│ │ per ogni id rimasto in idsSet: │ │
│ │ → deleteThumbsById │ │
│ │ → deleteFromDB │ │
│ │ → recordChange("removed") │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 7. scanPhoto ritorna newFiles │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 8. scanPhotosUser aggrega tutti i newFiles │
└──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 9. /scan risponde al client │
└──────────────────────────────────────────────┘
🟢 Cosa garantisce questo flusso
✔ /scan viene eseguito UNA sola volta
✔ scanPhotosUser viene eseguito UNA sola volta
✔ scanPhoto viene eseguito UNA sola volta per cartella
✔ scanPhotoCartella viene eseguito UNA sola volta
✔ gli orfani vengono eliminati UNA sola volta
✔ 1 added, 1 removed (mai più 2 removed)
✔ conteggio file corretto
✔ nessuna interferenza con “Common”
🔥 Vuoi anche la versione “diagramma a blocchi” o “diagramma a frecce” più compatto?
Se vuoi, posso anche farti un diagramma visivo del flusso completo, così lo vedi in un colpo d’occhio.
┌──────────────┐
│ /scan │
└───────┬──────┘
│
▼
┌──────────────────────────┐
│ 1. Autenticazione JWT │
└──────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ 2. Middleware GET (PATCH applicata) │
│ → NON aggiunge più "Common" │
│ → /scan usa SOLO req.user.name │
└────────────────────────────────────────┘
│
▼
┌────────────────────────────────┐
│ 3. scanPhotosUser(user) │
└────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐ │ 4. PRIMA PASSATA (ricorsiva) │ │ countFilesUser() │ │ → entra in tutte le sottocartelle │ │ → conta SOLO i file supportati │ │ → NON tocca DB │ └──────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────┐ │ 5. SECONDA PASSATA │ │ per ogni cartella in /original: │ │ → scanPhoto(cartella) │ └──────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────┐ │ 6. scanPhoto(cartella) │ │ → chiama scanPhotoCartella() UNA volta │ └──────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────┐ │ 7. scanPhotoCartella() │ │ │ │ 7.1 Recupera ID dal DB → idsSet │ │ 7.2 Scansiona file reali (scanCartella) │ │ → scanPhotoSingle() │ │ → idsSet.delete(id) │ │ 7.3 ORFANI (solo alla fine) │ │ → deleteThumbsById │ │ → deleteFromDB │ │ → recordChange("removed") │ └──────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────┐ │ 8. scanPhoto ritorna newFiles │ └────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────┐ │ 9. scanPhotosUser aggrega tutti i newFiles │ └──────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────┐ │ 10. Risposta al client │ └──────────────────────────┘
Perfetto Fabio — ora che abbiamo integrato la cancellazione delle cartelle eliminate e la funzione modulare deleteFolderForUser(), ti spiego esattamente cosa fa /scan adesso, passo per passo, in modo chiaro e completo.
Questa è la versione vera, aggiornata, precisa del comportamento attuale.
🔵 1. L’utente chiama /scan
✔ Se è Admin
- scansiona Common
- scansiona tutti gli utenti presenti in
users.json
✔ Se è utente normale
- scansiona solo il proprio spazio
🔵 2. Dentro scanPhotosUser(user) succede questo
Fase A — Lettura cartelle reali
Legge:
/photos/<user>/original/
e ottiene la lista delle cartelle realmente presenti sul filesystem.
Esempio:
["Vacanze2023", "Lavoro", "Gatti"]
🔵 3. Rilevamento cartelle eliminate (NOVITÀ)
Ora c’è la parte nuova e fondamentale:
✔ Recupera tutte le cartelle presenti nel DB per quell’utente
(es. cartelle che contengono record)
✔ Confronta DB vs filesystem
Se nel DB c’è:
["Vacanze2023", "Lavoro", "Gatti", "VecchiaCartella"]
ma sul disco c’è:
["Vacanze2023", "Lavoro", "Gatti"]
allora:
"VecchiaCartella" è stata cancellata dal filesystem
👉 A questo punto viene chiamata:
deleteFolderForUser(user, "VecchiaCartella")
Che fa:
- elimina tutti i record DB della cartella
- registra removed per ogni file
- elimina tutta la cartella thumbs residua:
/photos/<user>/thumbs/VecchiaCartella/
🔥 Risultato:
DB pulito + thumbs puliti
anche se la cartella originale è stata cancellata manualmente.
🔵 4. Fase B — Conteggio file reali
Viene eseguita la prima passata ricorsiva:
countFilesUser()
Serve solo per:
- contare i file reali
- calcolare la percentuale
- mostrare il progresso
Non modifica nulla.
🔵 5. Fase C — Scansione vera (UNA sola volta per cartella)
Per ogni cartella reale:
scanPhoto(cartella)
Che:
- scansiona i file reali
- aggiorna il DB
- genera “added”
- rileva orfani solo dentro quella cartella
- elimina thumbs e DB per gli orfani
- registra “removed”
🔵 6. Fine scan
Restituisce:
- lista dei nuovi file
- log completo
- DB aggiornato
- thumbs aggiornati