fix: lazy-load Wasabi URLs to prevent socket.io timeout — check local files first, generate signed URLs on-demand
continuous-integration/webhook Deploy concluído (VPS4)

This commit is contained in:
VPS 4 Deploy Agent
2026-05-30 17:27:44 +02:00
parent 39d162c282
commit 02dcbc3fae
+40 -27
View File
@@ -159,19 +159,9 @@ router.get('/patients', async (req, res) => {
params
);
// Converter thumb_filename para URL completa (Wasabi ou local)
// Lazy-load URLs para thumbnails (carrega em paralelo quando o frontend chamar)
for (const row of rows) {
if (row.thumb_filename) {
try {
const thumbUrl = await storage.getImageUrl(row.thumb_filename, row.client_name, row.patient_name);
row.thumb_url = thumbUrl || `/uploads/${row.thumb_filename}`;
} catch (e) {
console.error('Erro ao gerar URL de thumbnail:', e);
row.thumb_url = `/uploads/${row.thumb_filename}`;
}
} else {
row.thumb_url = '';
}
row.thumb_url = row.thumb_filename ? `/api/images/${row.id}/thumbnail` : '';
}
res.json(rows);
@@ -201,22 +191,10 @@ router.get('/by-patient', async (req, res) => {
[patientName, showDisabled ? 0 : 1]
);
// Converter filenames para URLs completas (Wasabi ou local)
// Adicionar lazy-load URLs (não fazer requisições async aqui)
for (const image of images) {
try {
if (image.filename) {
const fileUrl = await storage.getImageUrl(image.filename, image.client_name, image.patient_name);
image.file_url = fileUrl || `/uploads/${image.filename}`;
}
if (image.thumb_filename) {
const thumbUrl = await storage.getImageUrl(image.thumb_filename, image.client_name, image.patient_name);
image.thumb_url = thumbUrl || `/uploads/${image.thumb_filename}`;
}
} catch (e) {
console.error('Erro ao gerar URL para imagem:', e);
image.file_url = image.file_url || `/uploads/${image.filename}`;
image.thumb_url = image.thumb_url || `/uploads/${image.thumb_filename}`;
}
image.file_url = `/api/images/${image.id}/file-url`;
image.thumb_url = `/api/images/${image.id}/thumbnail`;
}
res.json(images);
@@ -489,6 +467,41 @@ router.delete('/:id', async (req, res) => {
}
});
// ================================================================
// GET /api/images/:id/thumbnail — Retorna URL da thumbnail
// (lazy-loaded para não bloquear listagens)
// ================================================================
router.get('/:id/thumbnail', async (req, res) => {
try {
const image = await db.get('SELECT thumb_filename, filename, client_name, patient_name FROM images WHERE id = $1', [req.params.id]);
if (!image) return res.status(404).json({ error: 'Imagem não encontrada' });
const fileToCheck = image.thumb_filename || image.filename;
let url;
// Tenta URL local primeiro (mais rápido)
const fsSync = require('fs');
const path = require('path');
const localPath = path.join(process.env.UPLOAD_DIR || '/app/uploads', fileToCheck);
if (fsSync.existsSync(localPath)) {
url = `/uploads/${fileToCheck}`;
} else {
// Se não existe localmente, tenta Wasabi
try {
const wasabiUrl = await storage.getImageUrl(fileToCheck, image.client_name, image.patient_name, false);
url = wasabiUrl || `/uploads/${fileToCheck}`;
} catch (e) {
console.error('Erro ao gerar URL Wasabi para thumbnail:', e);
url = `/uploads/${fileToCheck}`;
}
}
res.json({ url });
} catch (e) {
res.status(500).json({ error: e.message });
}
});
// ================================================================
// GET /api/images/:id/file-url — Retorna a URL de visualização
// full-res de uma imagem (para o painel Original do modal)