b6b345f245
- 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.
169 lines
4.0 KiB
JavaScript
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,
|
|
};
|