const pg = require('pg'); const { S3Client, ListBucketsCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3'); const pool = new pg.Pool({ connectionString: 'postgresql://edumanager:EduManager2026!Seguro@150.230.87.131:5432/edumanager' }); const s3Client = new S3Client({ endpoint: 'http://150.230.87.131:9000', region: 'us-east-1', credentials: { accessKeyId: 'minioadmin', secretAccessKey: 'MiniO2026!Seguro', }, forcePathStyle: true, }); async function main() { try { console.log('--- 1. BUSCANDO TODAS AS TABELAS E DADOS DO POSTGRESQL ---'); const { rows: tables } = await pool.query("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'"); console.log(`Encontradas ${tables.length} tabelas no banco de dados.`); let dbContentDump = ''; for (const t of tables) { const tableName = t.table_name; try { const { rows } = await pool.query(`SELECT * FROM "${tableName}"`); dbContentDump += JSON.stringify(rows) + ' '; } catch (err) { console.warn(`Aviso: não foi possível ler a tabela ${tableName}:`, err.message); } } console.log(`Dumping de referências concluído (${(dbContentDump.length / 1024 / 1024).toFixed(2)} MB).`); console.log('\n--- 2. LISTANDO ARQUIVOS NO STORAGE MINIO ---'); const bucketsData = await s3Client.send(new ListBucketsCommand({})); const buckets = bucketsData.Buckets || []; console.log(`Encontrados ${buckets.length} buckets no MinIO.`); const allFiles = []; let totalStorageSize = 0; for (const bucket of buckets) { try { const objects = await s3Client.send(new ListObjectsV2Command({ Bucket: bucket.Name })); const contents = objects.Contents || []; console.log(`Bucket [${bucket.Name}]: ${contents.length} arquivos encontrados.`); for (const obj of contents) { totalStorageSize += obj.Size || 0; allFiles.push({ bucket: bucket.Name, key: obj.Key, size: obj.Size || 0, url: `/storage/${bucket.Name}/${obj.Key}` }); } } catch (err) { console.warn(`Não foi possível listar objetos do bucket ${bucket.Name}:`, err.message); } } console.log(`Total geral no MinIO: ${(totalStorageSize / 1024 / 1024).toFixed(2)} MB (${allFiles.length} arquivos).`); console.log('\n--- 3. FILTRANDO ARQUIVOS NÃO UTILIZADOS ---'); const unusedFiles = []; const usedFiles = []; for (const file of allFiles) { const hasReference = dbContentDump.includes(file.key) || dbContentDump.includes(file.url); if (hasReference) { usedFiles.push(file); } else { unusedFiles.push(file); } } const totalUnusedSize = unusedFiles.reduce((acc, curr) => acc + curr.size, 0); console.log(`\nRESULTADOS:`); console.log(`- Arquivos em Uso: ${usedFiles.length}`); console.log(`- Arquivos Órfãos (NÃO usados): ${unusedFiles.length}`); console.log(`- Espaço sendo desperdiçado: ${(totalUnusedSize / 1024 / 1024).toFixed(2)} MB`); if (unusedFiles.length > 0) { console.log('\n--- LISTA DE ARQUIVOS NÃO UTILIZADOS ---'); unusedFiles.forEach((file, index) => { console.log(`${index + 1}. Bucket: [${file.bucket}] | Arquivo: ${file.key} | Tamanho: ${(file.size / 1024).toFixed(2)} KB`); }); } else { console.log('\nExcelente! Todos os arquivos armazenados no MinIO estão sendo referenciados no banco de dados!'); } } catch (error) { console.error('Erro na execução:', error); } finally { await pool.end(); } } main();