feat: Adicionado timeout assíncrono para ACK do Cliente Windows
continuous-integration/webhook Deploy concluído (VPS4)

This commit is contained in:
VPS 4 Deploy Agent
2026-06-02 20:55:21 +02:00
parent 34ef3efe1f
commit 5d2ba1a178
9 changed files with 95 additions and 33 deletions
+46 -21
View File
@@ -2,10 +2,44 @@ const express = require('express');
const router = express.Router();
const db = require('../database');
const imageProcessor = require('../image-processor');
const crypto = require('crypto');
const path = require('path');
const fs = require('fs').promises;
const storage = require('../storage');
async function emitAndAwaitAck(io, action, payload) {
if (!io) return { success: true, warning: 'Socket.IO não inicializado no servidor.' };
const eventId = crypto.randomUUID();
payload.eventId = eventId;
payload.action = action;
const ackPromise = new Promise((resolve) => {
if (global.pendingAcks) {
global.pendingAcks.set(eventId, resolve);
setTimeout(() => {
if (global.pendingAcks.has(eventId)) {
global.pendingAcks.delete(eventId);
resolve(null); // Timeout
}
}, 4000);
} else {
resolve(null);
}
});
io.emit('remote-crud-patient', payload);
const result = await ackPromise;
if (result && result.success) {
return { success: true, message: `Sincronizado com PC: ${result.pcName || 'Desconhecido'}`, ackInfo: result };
} else if (result && !result.success) {
return { success: true, warning: `Erro no app Windows (${result.pcName || 'Desconhecido'}): ${result.error || 'Erro local'}` };
} else {
return { success: true, warning: 'Salvo na nuvem, porém o App Windows não respondeu. Verifique se o PC está ligado e conectado.' };
}
}
// ================================================================
// GET /api/images/unique-clients - Buscar lista leve de clínicas
// ================================================================
@@ -217,7 +251,6 @@ router.post('/patients', async (req, res) => {
const fullName = `${firstName || ''} ${lastName || ''}`.trim();
if (!fullName) return res.status(400).json({ error: 'Nome obrigatório' });
const crypto = require('crypto');
const dummyGuid = crypto.randomUUID();
await db.run(
@@ -235,14 +268,11 @@ router.post('/patients', async (req, res) => {
);
const io = req.app.get('io') || global.io;
if (io) {
io.emit('remote-crud-patient', {
action: 'create',
patient: { id: dummyGuid, firstName, lastName, doctor, birthday, gender, phone, remark, fullName }
});
}
const syncResult = await emitAndAwaitAck(io, 'create', {
patient: { id: dummyGuid, firstName, lastName, doctor, birthday, gender, phone, remark, fullName }
});
res.json({ success: true, message: 'Paciente criado com sucesso' });
res.json(syncResult);
} catch (error) {
console.error('Erro ao criar paciente:', error);
res.status(500).json({ error: error.message });
@@ -286,15 +316,12 @@ router.put('/patients/:name', async (req, res) => {
);
const io = req.app.get('io') || global.io;
if (io) {
io.emit('remote-crud-patient', {
action: 'update',
oldName: oldName,
patient: { newName: newName?.trim(), doctor, remark }
});
}
res.json({ success: true, updated: result.changes });
const syncResult = await emitAndAwaitAck(io, 'update', {
oldName: oldName,
patient: { newName: newName?.trim(), doctor, remark }
});
res.json({ ...syncResult, updated: result.changes });
} catch (error) {
console.error('Erro ao editar paciente:', error);
res.status(500).json({ error: error.message });
@@ -318,11 +345,9 @@ router.delete('/by-patient', async (req, res) => {
await db.run('DELETE FROM images WHERE patient_name = $1', [patientName]);
const io = req.app.get('io') || global.io;
if (io) {
io.emit('remote-crud-patient', { action: 'delete', patientName });
}
const syncResult = await emitAndAwaitAck(io, 'delete', { patientName });
res.json({ success: true, count: images.length });
res.json({ ...syncResult, count: images.length });
} catch (error) {
console.error('Erro ao excluir imagens do paciente:', error);
res.status(500).json({ error: error.message });