Files
Zumri-Backend/app/utils/documentJob.util.js
T
Sathira Sri Sathara b6b345f245 feat: Implement Phase 2 cross-cutting services with email and notification enhancements
- Refactor email verification and password reset utilities to use new email service.
- Introduce email delivery queue and notification delivery model for better tracking.
- Enhance file validation and storage services for improved security and ownership management.
- Add cron job for cleaning inactive notifications with retention policy.
- Update document worker to handle document generation and storage more efficiently.
- Implement logging improvements in activity and log workers.
- Create comprehensive documentation for new API endpoints and services.
- Add unit tests for file validation and notification policies to ensure robustness.
2026-09-03 14:22:34 +05:30

169 lines
4.0 KiB
JavaScript

/**
* 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<object>} 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<object>} 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<object>} 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<boolean>} 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>} 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>} 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,
};