/** * Copyright (c) 2026 Niolla * All rights reserved. * * This source code is proprietary and confidential. * Unauthorized copying, modification, distribution, or use * of this file, via any medium, is strictly prohibited. */ // app/utils/documentJob.util.js const documentQueue = require("../queues/document.queue"); /** * Queue a document generation job * @param {string} document - Document type (e.g., 'precost') * @param {string} documentType - Format (e.g., 'pdf', 'excel') * @param {object} data - Data to pass to document generator * @returns {Promise} Job object with id */ const queueDocumentJob = async (document, documentType, data) => { try { const job = await documentQueue .add("generate-document", { document, documentType, data, }); return { success: true, jobId: job.id, createdAt: new Date(), }; } catch (error) { throw new Error(`Failed to queue document job: ${error.message}`); } }; /** * Get job status * @param {string|number} jobId - Job ID * @returns {Promise} Job status and details */ const getDocumentJobStatus = async (jobId) => { try { const job = await documentQueue .getJob(jobId); if (!job) { return { success: false, message: "Job not found", }; } const state = await job.getState(); const result = job.returnvalue; return { success: true, jobId: job.id, state, result: state === "completed" ? result : null, error: state === "failed" ? job.failedReason : null, createdAt: new Date(job.timestamp), startedAt: job.processedOn ? new Date(job.processedOn) : null, completedAt: job.finishedOn ? new Date(job.finishedOn) : null, }; } catch (error) { throw new Error(`Failed to get job status: ${error.message}`); } }; /** * Wait for job completion with timeout * @param {string|number} jobId - Job ID * @param {number} timeout - Timeout in milliseconds (default: 300000 = 5 minutes) * @returns {Promise} Job result when completed */ const waitForDocumentJob = async (jobId, timeout = 300000) => { try { const job = await documentQueue .getJob(jobId); if (!job) { throw new Error("Job not found"); } return await job.waitUntilFinished( { timeout }, documentQueue .events ); } catch (error) { throw new Error(`Failed to wait for job: ${error.message}`); } }; /** * Remove a job from queue * @param {string|number} jobId - Job ID * @returns {Promise} Success status */ const cancelDocumentJob = async (jobId) => { try { const job = await documentQueue .getJob(jobId); if (!job) { throw new Error("Job not found"); } await job.remove(); return true; } catch (error) { throw new Error(`Failed to cancel job: ${error.message}`); } }; /** * Get all active jobs * @returns {Promise} Array of active job details */ const getActiveJobs = async () => { try { const jobs = await documentQueue .getActiveCount(); const activeJobs = await documentQueue .getJobs(["active"], 0, -1); return { count: jobs, jobs: activeJobs.map((job) => ({ id: job.id, data: job.data, state: "active", progress: job.progress(), })), }; } catch (error) { throw new Error(`Failed to get active jobs: ${error.message}`); } }; /** * Get all pending jobs * @returns {Promise} Array of pending job details */ const getPendingJobs = async () => { try { const jobs = await documentQueue .getWaitingCount(); const pendingJobs = await documentQueue .getJobs(["waiting"], 0, -1); return { count: jobs, jobs: pendingJobs.map((job) => ({ id: job.id, data: job.data, state: "waiting", })), }; } catch (error) { throw new Error(`Failed to get pending jobs: ${error.message}`); } }; module.exports = { queueDocumentJob, getDocumentJobStatus, waitForDocumentJob, cancelDocumentJob, getActiveJobs, getPendingJobs, };