2024-06-17 10:47:36 -07:00
const axios = require ( "axios" );
const ping = require ( "ping" );
const logger = require ( "../utils/logger" );
2024-06-17 13:52:20 -07:00
const Check = require ( "../models/Check" );
2024-06-24 10:59:18 -07:00
const { Console } = require ( "winston/lib/winston/transports" );
2024-06-17 10:47:36 -07:00
class NetworkService {
constructor ( db ) {
this . db = db ;
this . TYPE_PING = "ping" ;
this . TYPE_HTTP = "http" ;
this . SERVICE_NAME = "NetworkService" ;
2024-06-18 11:42:25 -07:00
this . NETWORK_ERROR = 5000 ;
2024-06-17 10:47:36 -07:00
}
2024-06-17 13:52:20 -07:00
/**
* Measures the response time of an asynchronous operation.
* @param {Function} operation - An asynchronous operation to measure.
* @returns {Promise<{responseTime: number, response: any}>} An object containing the response time in milliseconds and the response from the operation.
* @throws {Error} The error object from the operation, contains response time.
*/
2024-06-17 11:33:55 -07:00
async measureResponseTime ( operation ) {
2024-06-17 11:05:22 -07:00
const startTime = Date . now ();
2024-06-17 10:47:36 -07:00
try {
2024-06-17 11:33:55 -07:00
const response = await operation ();
const endTime = Date . now ();
return { responseTime : endTime - startTime , response };
} catch ( error ) {
2024-06-17 13:52:20 -07:00
const endTime = Date . now ();
error . responseTime = endTime - startTime ;
2024-06-17 11:33:55 -07:00
throw error ;
}
}
2024-06-17 13:52:20 -07:00
/**
* Handles the ping operation for a given job, measures its response time, and logs the result.
* @param {Object} job - The job object containing data for the ping operation.
* @returns {Promise<{boolean}} The result of logging and storing the check
*/
2024-06-17 11:33:55 -07:00
async handlePing ( job ) {
const operation = async () => {
2024-06-17 10:47:36 -07:00
const response = await ping . promise . probe ( job . data . url );
2024-06-17 11:33:55 -07:00
return response ;
};
try {
const { responseTime , response } = await this . measureResponseTime (
operation
);
2024-06-17 10:47:36 -07:00
const isAlive = response . alive ;
2024-06-18 11:42:25 -07:00
const check = new Check ({
monitorId : job . data . _id ,
status : isAlive ,
responseTime ,
});
return await this . logAndStoreCheck ( check );
2024-06-17 10:47:36 -07:00
} catch ( error ) {
2024-06-18 11:42:25 -07:00
const check = new Check ({
monitorId : job . data . _id ,
status : false ,
responseTime : error . responseTime ,
});
return await this . logAndStoreCheck ( check );
2024-06-17 10:47:36 -07:00
}
}
2024-06-17 13:52:20 -07:00
/**
* Handles the http operation for a given job, measures its response time, and logs the result.
* @param {Object} job - The job object containing data for the ping operation.
* @returns {Promise<{boolean}} The result of logging and storing the check
*/
2024-06-17 10:47:36 -07:00
async handleHttp ( job ) {
2024-06-18 11:42:25 -07:00
// Define operation for timing
2024-06-17 11:33:55 -07:00
const operation = async () => {
2024-06-17 10:47:36 -07:00
const response = await axios . get ( job . data . url );
2024-06-17 11:33:55 -07:00
return response ;
};
2024-06-18 11:42:25 -07:00
// attempt connection
2024-06-17 11:33:55 -07:00
try {
const { responseTime , response } = await this . measureResponseTime (
operation
);
2024-06-18 11:42:25 -07:00
// check if response is in the 200 range, if so, service is up
2024-06-17 10:47:36 -07:00
const isAlive = response . status >= 200 && response . status < 300 ;
2024-06-18 11:42:25 -07:00
//Create a check with relevant data
const check = new Check ({
monitorId : job . data . _id ,
status : isAlive ,
responseTime ,
statusCode : response . status ,
});
return await this . logAndStoreCheck ( check );
2024-06-17 10:47:36 -07:00
} catch ( error ) {
2024-06-18 11:42:25 -07:00
const check = new Check ({
monitorId : job . data . _id ,
status : false ,
responseTime : error . responseTime ,
});
// The server returned a response
if ( error . response ) {
check . statusCode = error . response . status ;
} else {
check . statusCode = this . NETWORK_ERROR ;
}
return await this . logAndStoreCheck ( check );
2024-06-17 10:47:36 -07:00
}
}
2024-06-18 11:42:25 -07:00
2024-06-17 13:52:20 -07:00
/**
* Retrieves the status of a given job based on its type.
* For unsupported job types, it logs an error and returns false.
*
* @param {Object} job - The job object containing data necessary for processing.
* @returns {Promise<boolean>} The status of the job if it is supported and processed successfully, otherwise false.
*/
2024-06-17 10:47:36 -07:00
async getStatus ( job ) {
2024-06-17 11:05:22 -07:00
switch ( job . data . type ) {
case this . TYPE_PING :
return await this . handlePing ( job );
case this . TYPE_HTTP :
return await this . handleHttp ( job );
default :
2024-06-17 13:52:20 -07:00
logger . error ( `Unsupported type: ${ job . data . type } ` , {
2024-06-17 11:05:22 -07:00
service : this . SERVICE_NAME ,
2024-06-17 13:52:20 -07:00
jobId : job . id ,
2024-06-17 11:05:22 -07:00
});
return false ;
2024-06-17 10:47:36 -07:00
}
}
2024-06-17 13:52:20 -07:00
/**
* Logs and stores the result of a check for a specific job.
* This function creates a new Check object with the job's details and the result of the check,
* then attempts to save this object to the database. If the save operation is successful,
* it returns the status of the inserted check. If an error occurs during the save operation,
* it logs the error and returns false.
*
* @param {Object} job - The job object containing data necessary for the check.
* @param {boolean} isAlive - The result of the check, indicating if the target is alive.
* @param {number} responseTime - The response time measured during the check.
* @param {Error} [error=null] - Optional error object if an error occurred during the check.
* @returns {Promise<boolean>} The status of the inserted check if successful, otherwise false.
*/
2024-06-18 11:42:25 -07:00
async logAndStoreCheck ( check ) {
2024-06-17 13:52:20 -07:00
try {
const insertedCheck = await check . save ();
return insertedCheck . status ;
} catch ( error ) {
2024-06-24 10:59:18 -07:00
logger . error ( `Error wrtiting check for ${ check . monitorId } ` , {
2024-06-17 13:52:20 -07:00
service : this . SERVICE_NAME ,
2024-06-24 10:59:18 -07:00
monitorId : check . monitorId ,
2024-06-17 13:52:20 -07:00
error : error ,
});
return false ;
2024-06-17 10:47:36 -07:00
}
}
}
module . exports = NetworkService ;