Revert SSE streaming for PDF import, use synchronous flow
SSE streaming added unnecessary complexity and latency due to buffering issues across Node.js event loop, Nginx proxy, and Docker layers. Reverted to a simple synchronous request/response for PDF conversion. Kept extractLlmErrorMessage for user-friendly LLM errors, lazy-loaded pdf-parse, and extended Nginx timeout.
This commit is contained in:
@@ -3,7 +3,7 @@ import multer from 'multer';
|
||||
import { asyncHandler } from '../utils';
|
||||
import { importStatement, isValidationError } from '../services/import';
|
||||
import {
|
||||
convertPdfToStatementStreaming,
|
||||
convertPdfToStatement,
|
||||
isPdfConversionError,
|
||||
} from '../services/pdfToStatement';
|
||||
|
||||
@@ -28,10 +28,6 @@ function isJsonFile(file: { mimetype: string; originalname: string }): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function sseWrite(res: import('express').Response, data: Record<string, unknown>) {
|
||||
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
||||
}
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.post(
|
||||
@@ -55,68 +51,28 @@ router.post(
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPdfFile(file)) {
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
res.setHeader('X-Accel-Buffering', 'no');
|
||||
res.socket?.setNoDelay(true);
|
||||
res.flushHeaders();
|
||||
|
||||
try {
|
||||
const converted = await convertPdfToStatementStreaming(
|
||||
file.buffer,
|
||||
(stage, progress, message) => {
|
||||
sseWrite(res, { stage, progress, message });
|
||||
},
|
||||
);
|
||||
|
||||
if (isPdfConversionError(converted)) {
|
||||
sseWrite(res, {
|
||||
stage: 'error',
|
||||
message: converted.message,
|
||||
});
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await importStatement(converted);
|
||||
if (isValidationError(result)) {
|
||||
sseWrite(res, {
|
||||
stage: 'error',
|
||||
message: (result as { message: string }).message,
|
||||
});
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
sseWrite(res, {
|
||||
stage: 'done',
|
||||
progress: 100,
|
||||
result,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('SSE import error:', err);
|
||||
sseWrite(res, {
|
||||
stage: 'error',
|
||||
message: 'Внутренняя ошибка сервера',
|
||||
});
|
||||
}
|
||||
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// JSON files — synchronous response as before
|
||||
let body: unknown;
|
||||
try {
|
||||
body = JSON.parse(file.buffer.toString('utf-8'));
|
||||
} catch {
|
||||
res.status(400).json({
|
||||
error: 'BAD_REQUEST',
|
||||
message: 'Некорректный JSON-файл',
|
||||
});
|
||||
return;
|
||||
|
||||
if (isPdfFile(file)) {
|
||||
const converted = await convertPdfToStatement(file.buffer);
|
||||
if (isPdfConversionError(converted)) {
|
||||
res.status(converted.status).json({
|
||||
error: converted.error,
|
||||
message: converted.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
body = converted;
|
||||
} else {
|
||||
try {
|
||||
body = JSON.parse(file.buffer.toString('utf-8'));
|
||||
} catch {
|
||||
res.status(400).json({
|
||||
error: 'BAD_REQUEST',
|
||||
message: 'Некорректный JSON-файл',
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const result = await importStatement(body);
|
||||
|
||||
Reference in New Issue
Block a user