diff --git a/src/controllers/timeEntryController.js b/src/controllers/timeEntryController.js index b8114633c..d144db6bc 100644 --- a/src/controllers/timeEntryController.js +++ b/src/controllers/timeEntryController.js @@ -1,5 +1,6 @@ const moment = require('moment-timezone'); const mongoose = require('mongoose'); +const { v4: uuidv4 } = require('uuid'); const logger = require('../startup/logger'); const UserProfile = require('../models/userProfile'); const Project = require('../models/project'); @@ -1367,21 +1368,16 @@ const timeEntrycontroller = function (TimeEntry) { return newTotalIntangibleHrs; }; + const recalculationTaskQueue = []; + /** - * recalculate the hoursByCatefory for all users and update the field + * recalculate the hoursByCategory for all users and update the field */ - const recalculateHoursByCategoryAllUsers = async function (req, res) { + const recalculateHoursByCategoryAllUsers = async function (taskId) { const session = await mongoose.startSession(); session.startTransaction(); - let keepAliveInterval; try { - res.setHeader('Content-Type', 'text/plain'); - res.setHeader('Transfer-Encoding', 'chunked'); - keepAliveInterval = setInterval(() => { - res.write('Processing... keep connection alive\n'); - }, 150 * 1000); // interval of 150 seconds - const userprofiles = await UserProfile.find({}, '_id').lean(); const recalculationPromises = userprofiles.map(async (userprofile) => { @@ -1392,22 +1388,60 @@ const timeEntrycontroller = function (TimeEntry) { await Promise.all(recalculationPromises); await session.commitTransaction(); - clearInterval(keepAliveInterval); - res.write('finished the recalculation for hoursByCategory for all users\n'); - return res.end(); + + const recalculationTask = recalculationTaskQueue.find((task) => task.taskId === taskId); + if (recalculationTask) { + recalculationTask.status = 'Completed'; + recalculationTask.completionTime = new Date().toISOString(); + } } catch (err) { await session.abortTransaction(); - if (keepAliveInterval) { - clearInterval(keepAliveInterval); + const recalculationTask = recalculationTaskQueue.find((task) => task.taskId === taskId); + if (recalculationTask) { + recalculationTask.status = 'Failed'; + recalculationTask.completionTime = new Date().toISOString(); } + logger.logException(err); - res.write(`error: ${err.toString()}\n`); - return res.end(); } finally { session.endSession(); } }; + const startRecalculation = async function (req, res) { + const taskId = uuidv4(); + recalculationTaskQueue.push({ + taskId, + status: 'In progress', + startTime: new Date().toISOString(), + completionTime: null, + }); + if (recalculationTaskQueue.length > 10) { + recalculationTaskQueue.shift(); + } + + res.status(200).send({ + message: 'The recalculation task started in the background', + taskId, + }); + + setTimeout(() => recalculateHoursByCategoryAllUsers(taskId), 0); + }; + + const checkRecalculationStatus = async function (req, res) { + const { taskId } = req.params; + const recalculationTask = recalculationTaskQueue.find((task) => task.taskId === taskId); + if (recalculationTask) { + res.status(200).send({ + status: recalculationTask.status, + startTime: recalculationTask.startTime, + completionTime: recalculationTask.completionTime, + }); + } else { + res.status(404).send({ message: 'Task not found' }); + } + }; + /** * recalculate the totalIntangibleHrs for all users and update the field */ @@ -1452,9 +1486,10 @@ const timeEntrycontroller = function (TimeEntry) { getLostTimeEntriesForTeamList, backupHoursByCategoryAllUsers, backupIntangibleHrsAllUsers, - recalculateHoursByCategoryAllUsers, recalculateIntangibleHrsAllUsers, getTimeEntriesForReports, + startRecalculation, + checkRecalculationStatus, }; }; diff --git a/src/routes/timeentryRouter.js b/src/routes/timeentryRouter.js index 0fd7db716..cc8d04c57 100644 --- a/src/routes/timeentryRouter.js +++ b/src/routes/timeentryRouter.js @@ -32,9 +32,11 @@ const routes = function (TimeEntry) { ); TimeEntryRouter.route('/TimeEntry/recalculateHoursAllUsers/tangible').post( - controller.recalculateHoursByCategoryAllUsers, + controller.startRecalculation, ); + TimeEntryRouter.route('/TimeEntry/checkStatus/:taskId').get(controller.checkRecalculationStatus); + TimeEntryRouter.route('/TimeEntry/recalculateHoursAllUsers/intangible').post( controller.recalculateIntangibleHrsAllUsers, );