From 5d6cfb16bcf0c2cb9df9f5104a9cc4665367df27 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 28 Oct 2024 14:20:40 +0800 Subject: [PATCH] Refactor jobQueue to use new services --- Server/service/jobQueue.js | 157 +++++++++++++++++++++++++------------ 1 file changed, 105 insertions(+), 52 deletions(-) diff --git a/Server/service/jobQueue.js b/Server/service/jobQueue.js index 51e27fdb2..70f63e74f 100644 --- a/Server/service/jobQueue.js +++ b/Server/service/jobQueue.js @@ -16,7 +16,14 @@ class JobQueue { * @param {SettingsService} settingsService - The settings service * @throws {Error} */ - constructor(settingsService, logger, Queue, Worker) { + constructor( + statusService, + notificationService, + settingsService, + logger, + Queue, + Worker + ) { const settings = settingsService.getSettings() || {}; const { redisHost = "127.0.0.1", redisPort = 6379 } = settings; @@ -31,6 +38,8 @@ class JobQueue { this.workers = []; this.db = null; this.networkService = null; + this.statusService = statusService; + this.notificationService = notificationService; this.settingsService = settingsService; this.logger = logger; this.Worker = Worker; @@ -46,12 +55,21 @@ class JobQueue { static async createJobQueue( db, networkService, + statusService, + notificationService, settingsService, logger, Queue, Worker ) { - const queue = new JobQueue(settingsService, logger, Queue, Worker); + const queue = new JobQueue( + statusService, + notificationService, + settingsService, + logger, + Queue, + Worker + ); try { queue.db = db; queue.networkService = networkService; @@ -71,62 +89,97 @@ class JobQueue { } } + async isInMaintenanceWindow(monitorId) { + const maintenanceWindows = await this.db.getMaintenanceWindowsByMonitorId(monitorId); + // Check for active maintenance window: + const maintenanceWindowIsActive = maintenanceWindows.reduce((acc, window) => { + if (window.active) { + const start = new Date(window.start); + const end = new Date(window.end); + const now = new Date(); + const repeatInterval = window.repeat || 0; + + // If start is < now and end > now, we're in maintenance + if (start <= now && end >= now) return true; + + // If maintenance window was set in the past with a repeat, + // we need to advance start and end to see if we are in range + + while (start < now && repeatInterval !== 0) { + start.setTime(start.getTime() + repeatInterval); + end.setTime(end.getTime() + repeatInterval); + if (start <= now && end >= now) { + return true; + } + } + return false; + } + return acc; + }, false); + return maintenanceWindowIsActive; + } + + /** + * Creates a job handler function for processing jobs. + * + * @returns {Function} An async function that processes a job. + */ + createJobHandler() { + return async (job) => { + try { + // Get all maintenance windows for this monitor + const monitorId = job.data._id; + const maintenanceWindowActive = await this.isInMaintenanceWindow(monitorId); + // If a maintenance window is active, we're done + + if (maintenanceWindowActive) { + this.logger.info({ + message: `Monitor ${monitorId} is in maintenance window`, + service: SERVICE_NAME, + method: "createWorker", + }); + return; + } + + // Get the current status + const networkResponse = await this.networkService.getStatus(job); + // Handle status change + + const { monitor, statusChanged, prevStatus } = + await this.statusService.updateStatus(networkResponse); + + //If status hasn't changed, we're done + if (statusChanged == false) return; + + // if prevStatus is undefined, monitor is resuming, we're done + if (prevStatus === undefined) return; + + this.notificationService.handleNotifications({ + ...networkResponse, + monitor, + prevStatus, + }); + } catch (error) { + this.logger.error({ + message: error.message, + service: SERVICE_NAME, + method: "createWorker", + details: `Error processing job ${job.id}: ${error.message}`, + stack: error.stack, + }); + } + }; + } + /** * Creates a worker for the queue * Operations are carried out in the async callback * @returns {Worker} The newly created worker */ createWorker() { - const worker = new this.Worker( - QUEUE_NAME, - async (job) => { - try { - // Get all maintenance windows for this monitor - const monitorId = job.data._id; - const maintenanceWindows = - await this.db.getMaintenanceWindowsByMonitorId(monitorId); - // Check for active maintenance window: - const maintenanceWindowActive = maintenanceWindows.reduce((acc, window) => { - if (window.active) { - const start = new Date(window.start); - const end = new Date(window.end); - const now = new Date(); - const repeatInterval = window.repeat || 0; - - while ((start < now) & (repeatInterval !== 0)) { - start.setTime(start.getTime() + repeatInterval); - end.setTime(end.getTime() + repeatInterval); - } - - if (start < now && end > now) { - return true; - } - } - return acc; - }, false); - if (!maintenanceWindowActive) { - await this.networkService.getStatus(job); - } else { - this.logger.info({ - message: `Monitor ${monitorId} is in maintenance window`, - service: SERVICE_NAME, - method: "createWorker", - }); - } - } catch (error) { - this.logger.error({ - message: error.message, - service: SERVICE_NAME, - method: "createWorker", - details: `Error processing job ${job.id}: ${error.message}`, - stack: error.stack, - }); - } - }, - { - connection: this.connection, - } - ); + const worker = new this.Worker(QUEUE_NAME, this.createJobHandler(), { + connection: this.connection, + }); return worker; }