Merge pull request #154 from bluewave-labs/fix/error-handling

Improved network service error handling
This commit is contained in:
Alexander Holliday
2024-06-18 11:42:52 -07:00
committed by GitHub
5 changed files with 91 additions and 33 deletions
+13
View File
@@ -180,6 +180,18 @@ const deleteMonitor = async (req, res, next) => {
} }
}; };
const deleteAllMonitors = async (req, res) => {
try {
const deleteCount = await req.db.deleteAllMonitors();
return res
.status(200)
.json({ success: true, msg: `Deleted ${deleteCount} monitors` });
} catch (error) {
error.service = SERVICE_NAME;
next(error);
}
};
/** /**
* Edit a monitor by ID * Edit a monitor by ID
* @async * @async
@@ -219,5 +231,6 @@ module.exports = {
getMonitorsByUserId, getMonitorsByUserId,
createMonitor, createMonitor,
deleteMonitor, deleteMonitor,
deleteAllMonitors,
editMonitor, editMonitor,
}; };
+14 -2
View File
@@ -254,7 +254,19 @@ const deleteMonitor = async (req, res) => {
} }
return monitor; return monitor;
} catch (error) { } catch (error) {
console.log("CATHCING DELETE MONITOR ERROR"); throw error;
}
};
/**
* DELETE ALL MONITORS (TEMP)
*/
const deleteAllMonitors = async (req, res) => {
try {
const deletedCount = await Monitor.deleteMany({});
return deletedCount.deletedCount;
} catch (error) {
throw error; throw error;
} }
}; };
@@ -320,7 +332,6 @@ const createCheck = async (checkData) => {
const getChecks = async (monitorId) => { const getChecks = async (monitorId) => {
try { try {
const checks = await Check.find({ monitorId }); const checks = await Check.find({ monitorId });
console.log(checks);
return checks; return checks;
} catch (error) { } catch (error) {
throw error; throw error;
@@ -483,6 +494,7 @@ module.exports = {
getMonitorsByUserId, getMonitorsByUserId,
createMonitor, createMonitor,
deleteMonitor, deleteMonitor,
deleteAllMonitors,
editMonitor, editMonitor,
createCheck, createCheck,
getChecks, getChecks,
+20 -18
View File
@@ -15,34 +15,36 @@ const verifyJWT = (req, res, next) => {
const token = req.headers["authorization"]; const token = req.headers["authorization"];
// Make sure a token is provided // Make sure a token is provided
if (!token) { if (!token) {
const error = new Error(error.errorMessages.NO_AUTH_TOKEN); const error = new Error(errorMessages.NO_AUTH_TOKEN);
error.status = 401; error.status = 401;
error.service = SERVICE_NAME; error.service = SERVICE_NAME;
next(error); next(error);
return; return;
} }
// Make sure it is properly formatted // Make sure it is properly formatted
if (token.startsWith(TOKEN_PREFIX)) { if (!token.startsWith(TOKEN_PREFIX)) {
const parsedToken = token.slice(TOKEN_PREFIX.length, token.length); const error = new Error(errorMessages.INVALID_AUTH_TOKEN); // Instantiate a new Error object for improperly formatted token
// Verify the token's authenticity
jwt.verify(parsedToken, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
logger.error(errorMessages.INVALID_AUTH_TOKEN, {
service: SERVICE_NAME,
});
return res
.status(401)
.json({ success: false, msg: errorMessages.INVALID_AUTH_TOKEN });
}
//Add the user to the request object for use in the route
req.user = decoded;
next();
});
} else {
error.status = 400; error.status = 400;
error.service = SERVICE_NAME; error.service = SERVICE_NAME;
next(error); next(error);
return;
} }
const parsedToken = token.slice(TOKEN_PREFIX.length, token.length);
// Verify the token's authenticity
jwt.verify(parsedToken, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
logger.error(errorMessages.INVALID_AUTH_TOKEN, {
service: SERVICE_NAME,
});
return res
.status(401)
.json({ success: false, msg: errorMessages.INVALID_AUTH_TOKEN });
}
//Add the user to the request object for use in the route
req.user = decoded;
next();
});
}; };
module.exports = { verifyJWT }; module.exports = { verifyJWT };
+2
View File
@@ -18,4 +18,6 @@ router.post(
verifyOwnership(Monitor, "monitorId"), verifyOwnership(Monitor, "monitorId"),
monitorController.editMonitor monitorController.editMonitor
); );
router.delete("/delete/all", monitorController.deleteAllMonitors);
module.exports = router; module.exports = router;
+42 -13
View File
@@ -9,6 +9,7 @@ class NetworkService {
this.TYPE_PING = "ping"; this.TYPE_PING = "ping";
this.TYPE_HTTP = "http"; this.TYPE_HTTP = "http";
this.SERVICE_NAME = "NetworkService"; this.SERVICE_NAME = "NetworkService";
this.NETWORK_ERROR = 5000;
} }
/** /**
@@ -46,9 +47,20 @@ class NetworkService {
operation operation
); );
const isAlive = response.alive; const isAlive = response.alive;
return await this.logAndStoreCheck(job, isAlive, responseTime);
const check = new Check({
monitorId: job.data._id,
status: isAlive,
responseTime,
});
return await this.logAndStoreCheck(check);
} catch (error) { } catch (error) {
return await this.logAndStoreCheck(job, false, error.responseTime, error); const check = new Check({
monitorId: job.data._id,
status: false,
responseTime: error.responseTime,
});
return await this.logAndStoreCheck(check);
} }
} }
@@ -58,20 +70,45 @@ class NetworkService {
* @returns {Promise<{boolean}} The result of logging and storing the check * @returns {Promise<{boolean}} The result of logging and storing the check
*/ */
async handleHttp(job) { async handleHttp(job) {
// Define operation for timing
const operation = async () => { const operation = async () => {
const response = await axios.get(job.data.url); const response = await axios.get(job.data.url);
return response; return response;
}; };
// attempt connection
try { try {
const { responseTime, response } = await this.measureResponseTime( const { responseTime, response } = await this.measureResponseTime(
operation operation
); );
// check if response is in the 200 range, if so, service is up
const isAlive = response.status >= 200 && response.status < 300; const isAlive = response.status >= 200 && response.status < 300;
return await this.logAndStoreCheck(job, isAlive, responseTime);
//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);
} catch (error) { } catch (error) {
return await this.logAndStoreCheck(job, false, error.responseTime, error); 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);
} }
} }
/** /**
* Retrieves the status of a given job based on its type. * Retrieves the status of a given job based on its type.
* For unsupported job types, it logs an error and returns false. * For unsupported job types, it logs an error and returns false.
@@ -107,15 +144,7 @@ class NetworkService {
* @param {Error} [error=null] - Optional error object if an error occurred 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. * @returns {Promise<boolean>} The status of the inserted check if successful, otherwise false.
*/ */
async logAndStoreCheck(job, isAlive, responseTime, error = null) { async logAndStoreCheck(check) {
const check = new Check({
monitorId: job.data._id,
status: isAlive,
responseTime,
statusCode: 0,
message: error ? error.message : "",
});
try { try {
const insertedCheck = await check.save(); const insertedCheck = await check.save();
return insertedCheck.status; return insertedCheck.status;