Sì. Se in questo momento stai usando Scan invece del watcher, il percorso è diverso perché entra in gioco il vecchio scanner che abbiamo già visto, in particolare scanFile.js. Da quello che abbiamo verificato, il flusso è questo. Flusso Scan attuale SCAN │ ▼ scanner foto │ ▼ scanFile.js │ ┌──────┴───────┐ │ │ ▼ ▼ processFile() foto esistente? │ ▼ thumbnails │ ▼ photos DB │ ├──────────────► trigger SQLite │ │ │ ▼ │ face_scan_jobs │ │ │ ▼ │ FACE DAEMON │ ▼ photo_changes added / updated Questo deriva direttamente dal scanFile.js che abbiamo visto. Per una nuova foto fa: await db('photos').insert(...); await db('photo_changes').insert({ photo_id: meta.id, user, change_type: 'added', timestamp: ... }); e per una foto modificata: change_type: 'updated' Face Anche usando Scan, Face continua a utilizzare il daemon. Questo perché non è scanFile.js che avvia Face. È il trigger SQLite che abbiamo verificato: scanFile ↓ INSERT photos ↓ photos_face_enqueue_insert ↓ face_scan_jobs ↓ FACE DAEMON E per una modifica: UPDATE photos ↓ photos_face_enqueue_update ↓ face_scan_jobs ↓ FACE DAEMON Questa parte quindi è già correttamente disaccoppiata. Geocode invece va verificato Qui c'è una differenza importante. Nel nuovo scanPhotoSingle.js abbiamo visto esplicitamente: await enqueueGeocodeJob(...) quindi con Photo daemon sappiamo che: Photo daemon → geocode_jobs → Geocode daemon Nel pezzo di scanFile.js che abbiamo esaminato non abbiamo invece verificato l'enqueue geocode. Quindi non darei ancora per certo che lo Scan utilizzi il nuovo Geocode daemon. E la Gallery? Anche questa è diversa. Il vecchio Scan scrive: photo_changes ma abbiamo verificato che attualmente nessuno consuma photo_changes. Bisogna però ricordare che diverse route autoScan.js effettuano direttamente: wss.broadcastToUser(...) e il nostro grep aveva trovato vari: type: "added" dentro autoScan.js. Quindi è molto probabile che con lo Scan il percorso realtime sia: SCAN │ ▼ scanFile / scanner │ ▼ photos DB │ ▼ autoScan.js │ ▼ broadcastToUser() │ ▼ WebSocket │ ▼ sync.js │ ▼ Gallery e non utilizzi la nuova server_event_outbox, perché Scan viene eseguito dentro il processo server e può accedere direttamente al WebSocket. In sostanza oggi abbiamo probabilmente due strade NUOVA FOTO │ ┌────────────┴─────────────┐ │ │ SCAN WATCHER │ │ ▼ ▼ scanFile.js photo_ingest_jobs │ │ │ PHOTO DAEMON │ │ └────────► photos ◄────────┘ │ ▼ FACE trigger │ ▼ FACE DAEMON Per la gallery: SCAN │ └──► autoScan → WebSocket ──────────────► Gallery PHOTO DAEMON │ └──► server_event_outbox → Server → WS ─► Gallery Questa doppia strada può essere perfettamente corretta: l'outbox serve solo quando il produttore è un processo esterno al server. Se vuoi capire esattamente il flusso Scan senza supposizioni, il prossimo controllo ideale è: grep -nE "scanFile|broadcastToUser|type: ['\"]added|type: ['\"]updated|enqueueGeocode" \ routes/autoScan.js e: grep -nE "enqueueGeocode|geocode|broadcast|recordChange" \ api_v1/scanner/scanFile.js Con questi due output possiamo confrontare precisamente: SCAN vs WATCHER + PHOTO DAEMON e verificare se anche Scan usa i daemon Geocode e Face e come aggiorna la galleria.