photo_server_json_flutter_c.../scan_Funzionamento.md

18 KiB
Raw Blame History

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. Lutente chiama /scan

Quando fai:

GET /scan

succede questo:

✔ Il middleware JWT autentica lutente

✔ Il middleware GET non aggiunge più “Common”

→ quindi lo scan viene fatto solo per lutente 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 lID 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é:

  • /scan viene chiamato una sola volta
  • scanPhotosUser viene eseguito una sola volta
  • scanPhoto viene eseguito una sola volta
  • scanPhotoCartella viene eseguito una sola volta
  • gli orfani vengono eliminati una sola volta

Prima invece:

  • il middleware GET aggiungeva Common
  • quindi /scan scansionava 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 docchio.

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 lutente                      │
│    ✔ 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 docchio.

             ┌──────────────┐
             │   /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. Lutente 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 quellutente

(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

🟢 RIASSUNTO: COSA FA /scan ADESSO

✔ Scansiona solo cartelle realmente presenti

✔ Rileva cartelle eliminate dal filesystem

✔ Cancella TUTTI i thumbs residui della cartella eliminata

✔ Cancella TUTTI i record DB della cartella eliminata

✔ Registra “removed” per ogni file eliminato

✔ Scansiona ogni cartella UNA sola volta

✔ Nessun doppio removed

✔ Nessun orfano nascosto

✔ Nessuna doppia passata

✔ Nessun conflitto tra utenti

✔ Admin può scansionare tutti


🔥 Vuoi che ti preparo anche un diagramma aggiornato del flusso /scan con la nuova logica di cancellazione cartelle?