edumanagerpro2/manager/scratch/find_unused_files_internal.cjs

102 lines
3.9 KiB
JavaScript

const pg = require('pg');
const { S3Client, ListBucketsCommand, ListObjectsV2Command } = require('@aws-sdk/client-s3');
const DATABASE_URL = process.env.DATABASE_URL || 'postgresql://edumanager:EduManager2026!Seguro@postgres:5432/edumanager';
const pool = new pg.Pool({ connectionString: DATABASE_URL });
const MINIO_ENDPOINT = process.env.MINIO_ENDPOINT || 'minio';
const MINIO_PORT = process.env.MINIO_PORT || '9000';
const MINIO_ACCESS_KEY = process.env.MINIO_ACCESS_KEY || 'minioadmin';
const MINIO_SECRET_KEY = process.env.MINIO_SECRET_KEY || 'MiniO2026!Seguro';
const s3Client = new S3Client({
endpoint: `http://${MINIO_ENDPOINT}:${MINIO_PORT}`,
region: 'us-east-1',
credentials: {
accessKeyId: MINIO_ACCESS_KEY,
secretAccessKey: MINIO_SECRET_KEY,
},
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();