Skip to content

Commit

Permalink
FEAT(#508): Using time server for cron jobs
Browse files Browse the repository at this point in the history
  • Loading branch information
tholulomo committed Aug 20, 2024
1 parent d4f2f41 commit f44264b
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 18 deletions.
19 changes: 18 additions & 1 deletion resfulservice/spec/mocks/taskMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,22 @@ const fetchedCuration = {
}
};

const mockTimeApiResponse = {
year: 2024,
month: 6,
day: 6,
hour: 6,
minute: 44,
seconds: 38,
milliSeconds: 875,
dateTime: '2024-06-06T06:44:38.8753094',
date: '06/06/2024',
time: '06:44',
timeZone: 'US/Eastern',
dayOfWeek: 'Thursday',
dstActive: true
};

module.exports = {
mockTasks,
mockNonExistingService,
Expand All @@ -251,5 +267,6 @@ module.exports = {
searchedKnowledgeGraph,
mockElasticSearchChartsResult,
mockFavoriteChart,
fetchedCuration
fetchedCuration,
mockTimeApiResponse
};
7 changes: 7 additions & 0 deletions resfulservice/spec/sw/utils/worker-service.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const axios = require('axios');
const { expect } = require('chai');
const fs = require('fs');
const sinon = require('sinon');
Expand All @@ -21,6 +22,12 @@ const CuratedSamples = require('../../../src/models/curatedSamples');
const minioClient = require('../../../src/utils/minio');

describe('Worker Services', function () {
beforeEach(() => {
axiosStub = sinon
.stub(axios, 'get')
.resolves({ data: { dateTime: new Date().toISOString() } });
clock = sinon.useFakeTimers();
});
afterEach(() => sinon.restore());

context('workerManager', () => {
Expand Down
5 changes: 3 additions & 2 deletions resfulservice/src/sw/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ const mongoose = require('mongoose');
const { log } = require('../middlewares');
const WorkerService = require('./utils/worker-services');
const Debouncer = require('./utils/debouncer');
const { ServiceWorkerDebouncerTimer } = require('../../config/constant');

const env = process.env;

const catchAllHandler = (request, response) => {
const catchAllHandler = (_request, response) => {
response.writeHead(200, {
'Content-Type': 'application/json'
});
Expand Down Expand Up @@ -34,7 +35,7 @@ mongoose
});
const debouncedWorkerManager = Debouncer.debounce(
WorkerService.workerManager,
120000
ServiceWorkerDebouncerTimer
);
debouncedWorkerManager(log);
})
Expand Down
108 changes: 93 additions & 15 deletions resfulservice/src/sw/utils/worker-services.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
const sharp = require('sharp');
const fs = require('fs');
const axios = require('axios');
const CuratedSamples = require('../../models/curatedSamples');
const Task = require('../models/task');
const FileManager = require('../../utils/fileManager');
const KnowledgeController = require('../../controllers/kgWrapperController');
const minioClient = require('../../utils/minio');
const { log } = require('../../middlewares');
const {
SupportedFileResponseHeaders,
MinioBucket,
Expand All @@ -14,6 +16,90 @@ const { stringifyError } = require('../../utils/exit-utils');

const env = process.env;
const BUCKETNAME = env.MINIO_BUCKET ?? MinioBucket;
const TIME_API_URL =
'https://timeapi.io/api/Time/current/zone?timeZone=US/Eastern';

// Global variables to store the fetched time and date
let fetchedTime = null;
let fetchedDate = null;

// Function to fetch the current time from the API
async function fetchCurrentTime() {
log.info('fetchCurrentTime(): Function entry');
try {
const response = await axios.get(TIME_API_URL);
if (response.status === 200) {
const data = response.data;
log.info(`Fetched time: ${data.dateTime}`);
fetchedTime = new Date(data.dateTime);
fetchedDate = fetchedTime.toISOString().split('T')[0];
} else {
log.error('Failed to fetch time from the API');
throw new Error('Failed to fetch time from the API');
}
} catch (error) {
log.error(error);
}
}

// Function to calculate the remaining time until 12:00 AM in the correct timezone
function getRemainingTimeUntilMidnight() {
log.info('getRemainingTimeUntilMidnight(): Function entry');
const now = new Date();
const timezoneOffset = now.getTimezoneOffset() * 60000;
const nowInEST = new Date(now.getTime() - timezoneOffset + 3600000 * -5); // EST is UTC-5
const nextMidnight = new Date(nowInEST);
nextMidnight.setHours(0, 0, 0, 0);

// If it's already past 12:00 AM today, set nextMidnight to 12:00 AM the next day
if (nowInEST >= nextMidnight) {
nextMidnight.setDate(nextMidnight.getDate() + 1);
}

return nextMidnight - nowInEST;
}

// Function to check if the current time is between 12:00 AM and 3:00 AM
function isNightTime() {
log.info('isNightTime(): Function entry');
if (fetchedTime !== null) {
const startTime = new Date(fetchedTime);
startTime.setHours(0, 0, 0, 0);
const endTime = new Date(fetchedTime);
endTime.setHours(3, 0, 0, 0);
return fetchedTime >= startTime && fetchedTime < endTime;
} else {
return false;
}
}

// Function to update fetched time and date periodically
async function updateTimeIfNecessary() {
log.info('updateTimeIfNecessary(): Function entry');
const now = new Date();
const timezoneOffset = now.getTimezoneOffset() * 60000;
const nowInEST = new Date(now.getTime() - timezoneOffset + 3600000 * -5); // EST is UTC-5
const currentDate = nowInEST.toISOString().split('T')[0];

// Check if it's a new day
if (fetchedDate !== currentDate) {
await fetchCurrentTime();
} else {
// Increment fetchedTime by 3 minutes
fetchedTime = new Date(fetchedTime.getTime() + 3 * 60 * 1000);
}
}

// Initial fetch of the current time
fetchCurrentTime().then(() => {
// Set a timer to fetch the time from the API at 12:00 AM
const remainingTimeUntilMidnight = getRemainingTimeUntilMidnight();
setTimeout(async () => {
await fetchCurrentTime();
console.log('Fetched time at 12:00 AM:', fetchedTime);
}, remainingTimeUntilMidnight);
});

const serviceManager = {
convertImageToPng: {
serviceName: 'convertImageToPng',
Expand All @@ -27,13 +113,16 @@ const serviceManager = {
}
};

async function workerManager (logger) {
async function workerManager(logger) {
const tasks = await Task.find({
status: { $nin: [TaskStatusMap.MISSING, TaskStatusMap.DISABLED] }
});

if (!tasks.length) return;

await updateTimeIfNecessary();
logger.info('current time: ', fetchedTime);

tasks.forEach(async (task) => {
const service = serviceManager[task.serviceName];
if (!service) {
Expand Down Expand Up @@ -73,7 +162,7 @@ async function workerManager (logger) {
});
}

async function convertImageToPng ({ _id, info: { ref, sampleID } }, logger) {
async function convertImageToPng({ _id, info: { ref, sampleID } }, logger) {
logger.info('Worker-services.convertImageToPng - Function entry');
const pngFilePath = `${ref.split(/.tiff?/)[0]}.png`;
const pngFile = pngFilePath.split('mm_files/')[1];
Expand Down Expand Up @@ -215,7 +304,7 @@ async function convertImageToPng ({ _id, info: { ref, sampleID } }, logger) {
}
}

async function knowledgeRequest (
async function knowledgeRequest(
{ _id: uuid, info: { knowledgeId, req } },
logger
) {
Expand Down Expand Up @@ -268,7 +357,7 @@ const isObjectExistInMinio = async (bucketName, fileName) => {
}
};

async function checkFileExistence (filePath) {
async function checkFileExistence(filePath) {
try {
await fs.promises.access(filePath, fs.constants.F_OK);
return true;
Expand Down Expand Up @@ -297,15 +386,4 @@ const generateTempFileName = (filepath) => {
return `mm_files/failed_upload_${filename}`;
};

const isNightTime = () => {
const options = {
timeZone: 'America/New_York', // Specify the timezone
hour12: false, // Set to true for 12-hour format, false for 24-hour format
hour: '2-digit' // Set to '2-digit' to get the hour
};

const currentHour = new Date().toLocaleString('en-US', options);
return currentHour >= 0 && currentHour <= 3;
};

module.exports = { convertImageToPng, workerManager, knowledgeRequest };

0 comments on commit f44264b

Please sign in to comment.