Agent/server/src/export/worker.js

78 lines
2.5 KiB
JavaScript

'use strict';
const { Worker } = require('bullmq');
const db = require('../infra/db');
const audit = require('../audit/audit');
const { connection } = require('./queue');
const { generate } = require('./generator');
const exportService = require('./export.service');
const worker = new Worker(
'profile-exports',
async (job) => {
const { jobUuid, type, params } = job.data;
await db.execute(
"UPDATE export_jobs SET status = 'processing', progress = 10, started_at = NOW(), error = NULL WHERE job_uuid = ?",
[jobUuid],
);
await job.updateProgress(10);
const file = await generate(jobUuid, type, params);
await job.updateProgress(90);
await db.execute(
`UPDATE export_jobs
SET status = 'completed', progress = 100, file_name = ?, file_path = ?,
mime_type = ?, file_size = ?, file_hash = ?, completed_at = NOW()
WHERE job_uuid = ?`,
[file.fileName, file.filePath, file.mimeType, file.fileSize, file.fileHash, jobUuid],
);
await audit.log({
userId: Number(job.data.requestedBy),
clientType: 'system',
action: 'export_completed',
module: 'exports',
targetType: 'export_job',
targetId: jobUuid,
payload: { type, fileName: file.fileName, fileSize: file.fileSize, fileHash: file.fileHash },
});
return { fileName: file.fileName, fileHash: file.fileHash };
},
{
connection: connection.duplicate(),
concurrency: 2,
limiter: { max: 10, duration: 60 * 1000 },
},
);
worker.on('failed', async (job, error) => {
if (!job) return;
await db.execute(
"UPDATE export_jobs SET status = 'failed', progress = 0, error = ?, completed_at = NOW() WHERE job_uuid = ?",
[String(error.message || error).slice(0, 1000), job.data.jobUuid],
);
await audit.log({
userId: Number(job.data.requestedBy),
clientType: 'system',
action: 'export_failed',
module: 'exports',
targetType: 'export_job',
targetId: job.data.jobUuid,
payload: { type: job.data.type, error: String(error.message || error).slice(0, 500) },
});
});
const cleanupTimer = setInterval(() => {
exportService.cleanupExpired().catch((error) => console.error('[export-worker] cleanup failed:', error.message));
}, 60 * 60 * 1000);
async function shutdown() {
clearInterval(cleanupTimer);
await worker.close();
await connection.quit();
await db.close();
}
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
console.log('[export-worker] ready, concurrency=2');