From 9aec9d3a50578e908f0a1f4d5e363c80d6028b58 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Mon, 16 Mar 2026 16:27:55 +0100 Subject: [PATCH] refactor: rimuove cache destinazione e forza rescansione completa - elimina cache su disco in destination scanner - rimuove integrazione cache da main process - allinea messaggi progresso UI alla scansione completa - aggiorna README con comportamento senza cache --- README.md | 1 + main.js | 3 - renderer/renderer.js | 13 +-- services/destinationScanner.js | 169 +-------------------------------- 4 files changed, 5 insertions(+), 181 deletions(-) diff --git a/README.md b/README.md index c9bad23..6c21934 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Analizza una cartella o un archivio `.zip`, riconosce i file CAD (`.prt`, `.asm` ## Funzionalità - Smistamento da cartella o archivio ZIP (con drag & drop) +- Riscansione completa della destinazione a ogni processo (senza cache) - Routing automatico basato sul gruppo di cifre nel nome file - Gestione versioni: mantiene solo la versione più alta - Cartelle speciali: `__NON_SMISTATI`, `__DUPLICATI`, `__SALTATI` diff --git a/main.js b/main.js index c25baf1..8ca9952 100644 --- a/main.js +++ b/main.js @@ -4,7 +4,6 @@ const fs = require('fs-extra'); const { processFolder } = require('./services/folderProcessor'); const { processZip } = require('./services/zipProcessor'); -const { setCacheDir, clearCache } = require('./services/destinationScanner'); const { resolveUnroutedDir, listUnroutedFiles, @@ -128,7 +127,6 @@ Menu.setApplicationMenu(Menu.buildFromTemplate([ app.whenReady().then(async () => { await ensureRuntimeDirectory(); - setCacheDir(getRuntimeDirectory()); const persistedDestination = await loadPersistedDestination(); config = buildConfig(persistedDestination); createWindow(); @@ -226,7 +224,6 @@ ipcMain.handle('update-destination', async (_event, payload) => { config = buildConfig(destination); await persistDestination(config.destination); - await clearCache(); return { destination: config.destination }; }); diff --git a/renderer/renderer.js b/renderer/renderer.js index 6b639d5..17fcb14 100644 --- a/renderer/renderer.js +++ b/renderer/renderer.js @@ -35,30 +35,21 @@ function hideProgress() { let _indexFilesFound = 0; function updateProgress({ phase, current, total, file, scanned, folder }) { - if (phase === 'index-cache') { - // folderIndex dalla cache — avvia scansione veloce dei file - progressBar.max = total || 1; - progressBar.value = 0; - progressLabel.textContent = 'Struttura dalla cache — ricerca file CAD in corso...'; - return; - } else if (phase === 'scan') { + if (phase === 'scan') { _indexFilesFound = 0; progressLabel.textContent = 'Scansione file sorgente...'; progressBar.removeAttribute('value'); } else if (phase === 'index-dest') { - // scansione completa (nessuna cache) progressBar.max = total; progressBar.value = current; const filesInfo = _indexFilesFound > 0 ? ` — ${_indexFilesFound} file CAD trovati` : ''; progressLabel.textContent = `Analisi destinazione: ${current} / ${total}${folder ? ` — ${folder}` : ''}${filesInfo}`; } else if (phase === 'index-dup') { if (current !== undefined && total !== undefined) { - // scansione veloce (cache attiva): current/total = cartelle processate progressBar.max = total; progressBar.value = current; - progressLabel.textContent = `Ricerca file CAD: ${current} / ${total} cartelle`; + progressLabel.textContent = `Analisi destinazione: ${current} / ${total} cartelle`; } else { - // scansione completa: scanned = contatore file trovati _indexFilesFound = scanned; const dirInfo = progressBar.max > 0 ? `${progressBar.value} / ${progressBar.max} — ` : ''; progressLabel.textContent = `Analisi destinazione: ${dirInfo}${scanned} file CAD trovati`; diff --git a/services/destinationScanner.js b/services/destinationScanner.js index a31ef51..b566134 100644 --- a/services/destinationScanner.js +++ b/services/destinationScanner.js @@ -4,64 +4,12 @@ const { getCadInfo } = require('./router'); const CODE_FOLDER_REGEX = /^\d{3}$/; const MAX_SCAN_DEPTH = 6; -const CACHE_FILENAME = 'dest-index.cache.json'; - -let _cacheDir = null; - -function setCacheDir(dir) { - _cacheDir = dir; -} function toCadKey(cadInfo) { return String(cadInfo?.key || '').toLowerCase(); } -function getCacheFilePath() { - return _cacheDir ? path.join(_cacheDir, CACHE_FILENAME) : null; -} - -// ── Cache su disco (solo folderIndex — struttura cartelle) ───────────────── - -async function tryLoadFolderIndexCache(destinationRoot) { - const cacheFile = getCacheFilePath(); - if (!cacheFile) return null; - - try { - const raw = await fs.readJson(cacheFile); - if (raw?.destination !== destinationRoot) return null; - return { folderIndex: new Map(raw.folderIndex || []), savedAt: raw.savedAt }; - } catch { - return null; - } -} - -async function saveFolderIndexCache(destinationRoot, folderIndex) { - const cacheFile = getCacheFilePath(); - if (!cacheFile) return; - try { - await fs.writeJson(cacheFile, { - destination: destinationRoot, - savedAt: new Date().toISOString(), - folderIndex: [...folderIndex.entries()], - }); - } catch { - // cache non critica - } -} - -async function clearCache() { - const cacheFile = getCacheFilePath(); - if (!cacheFile) return; - try { - await fs.remove(cacheFile); - } catch { - // ignora - } -} - -// ── Scansione completa (folderIndex + cadKeyIndex in un unico passaggio) ─── - -async function fullScan(destinationRoot, onProgress) { +async function buildDestinationIndexes(destinationRoot, onProgress) { const folderIndex = new Map(); const cadKeyIndex = new Set(); @@ -148,117 +96,4 @@ async function fullScan(destinationRoot, onProgress) { return { folderIndex, cadKeyIndex }; } -// ── Scansione veloce dei file (usa il folderIndex già noto dalla cache) ──── -// -// Invece di traversare l'intero albero, legge direttamente SOLO le cartelle -// a 3 cifre già note. Questo riduce drasticamente le chiamate readdir su SMB. - -async function scanCadKeysFromFolderIndex(folderIndex, onProgress) { - const cadKeyIndex = new Set(); - const allFolderPaths = [...folderIndex.values()].flat(); - const total = allFolderPaths.length; - let completed = 0; - - await Promise.all( - allFolderPaths.map(async (folderPath) => { - for (const sub of ['A', 'M_B']) { - const subPath = path.join(folderPath, sub); - let entries; - try { - entries = await fs.readdir(subPath, { withFileTypes: true }); - } catch { - continue; - } - for (const entry of entries) { - if (!entry.isFile()) continue; - const cadInfo = getCadInfo(entry.name); - if (cadInfo) { - cadKeyIndex.add(toCadKey(cadInfo)); - } - } - } - - completed += 1; - onProgress?.({ phase: 'index-dup', current: completed, total }); - }) - ); - - return cadKeyIndex; -} - -// ── Entry point ──────────────────────────────────────────────────────────── - -async function isCacheStillValid(destinationRoot, cached) { - // Controlla le cartelle top-level E le cartelle a 3 cifre al loro interno. - // Costa 1 + N_top_level readdir — rileva nuove cartelle aggiunte da colleghi. - let currentEntries; - try { - currentEntries = await fs.readdir(destinationRoot, { withFileTypes: true }); - } catch { - return false; - } - - const currentDirNames = new Set( - currentEntries.filter((e) => e.isDirectory()).map((e) => e.name) - ); - - // Ricostruisce: topLevelDir → Set dalla cache - const cachedGroupsByTopDir = new Map(); - for (const [group, paths] of cached.folderIndex.entries()) { - for (const p of paths) { - const topDir = path.relative(destinationRoot, p).split(path.sep)[0]; - if (!cachedGroupsByTopDir.has(topDir)) cachedGroupsByTopDir.set(topDir, new Set()); - cachedGroupsByTopDir.get(topDir).add(group); - } - } - - const cachedDirNames = new Set(cachedGroupsByTopDir.keys()); - - // Controlla top-level - for (const name of currentDirNames) { - if (!cachedDirNames.has(name)) return false; - } - for (const name of cachedDirNames) { - if (!currentDirNames.has(name)) return false; - } - - // Controlla cartelle a 3 cifre dentro ogni top-level (solo nuove aggiunte) - for (const topDir of currentDirNames) { - let subEntries; - try { - subEntries = await fs.readdir(path.join(destinationRoot, topDir), { withFileTypes: true }); - } catch { - return false; - } - const cachedGroups = cachedGroupsByTopDir.get(topDir) || new Set(); - for (const e of subEntries) { - if (e.isDirectory() && CODE_FOLDER_REGEX.test(e.name) && !cachedGroups.has(e.name)) { - return false; // nuova cartella a 3 cifre rilevata - } - } - } - - return true; -} - -async function buildDestinationIndexes(destinationRoot, onProgress) { - if (!destinationRoot) { - return { folderIndex: new Map(), cadKeyIndex: new Set() }; - } - - const cached = await tryLoadFolderIndexCache(destinationRoot); - - if (cached && (await isCacheStillValid(destinationRoot, cached))) { - // folderIndex dalla cache (istantaneo), cadKeyIndex sempre fresco - onProgress?.({ phase: 'index-cache', savedAt: cached.savedAt, total: cached.folderIndex.size }); - const cadKeyIndex = await scanCadKeysFromFolderIndex(cached.folderIndex, onProgress); - return { folderIndex: cached.folderIndex, cadKeyIndex }; - } - - // Prima volta, cache invalidata o struttura cambiata: scansione completa - const result = await fullScan(destinationRoot, onProgress); - await saveFolderIndexCache(destinationRoot, result.folderIndex); - return result; -} - -module.exports = { buildDestinationIndexes, setCacheDir, clearCache, toCadKey }; +module.exports = { buildDestinationIndexes, toCadKey };