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
* @async
@@ -219,5 +231,6 @@ module.exports = {
getMonitorsByUserId,
createMonitor,
deleteMonitor,
deleteAllMonitors,
editMonitor,
};
+14 -2
View File
@@ -254,7 +254,19 @@ const deleteMonitor = async (req, res) => {
}
return monitor;
} 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;
}
};
@@ -320,7 +332,6 @@ const createCheck = async (checkData) => {
const getChecks = async (monitorId) => {
try {
const checks = await Check.find({ monitorId });
console.log(checks);
return checks;
} catch (error) {
throw error;
@@ -483,6 +494,7 @@ module.exports = {
getMonitorsByUserId,
createMonitor,
deleteMonitor,
deleteAllMonitors,
editMonitor,
createCheck,
getChecks,
+20 -18
View File
@@ -15,34 +15,36 @@ const verifyJWT = (req, res, next) => {
const token = req.headers["authorization"];
// Make sure a token is provided
if (!token) {
const error = new Error(error.errorMessages.NO_AUTH_TOKEN);
const error = new Error(errorMessages.NO_AUTH_TOKEN);
error.status = 401;
error.service = SERVICE_NAME;
next(error);
return;
}
// Make sure it is properly formatted
if (token.startsWith(TOKEN_PREFIX)) {
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();
});
} else {
if (!token.startsWith(TOKEN_PREFIX)) {
const error = new Error(errorMessages.INVALID_AUTH_TOKEN); // Instantiate a new Error object for improperly formatted token
error.status = 400;
error.service = SERVICE_NAME;
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 };
+2
View File
@@ -18,4 +18,6 @@ router.post(
verifyOwnership(Monitor, "monitorId"),
monitorController.editMonitor
);
router.delete("/delete/all", monitorController.deleteAllMonitors);
module.exports = router;
+42 -13
View File
@@ -9,6 +9,7 @@ class NetworkService {
this.TYPE_PING = "ping";
this.TYPE_HTTP = "http";
this.SERVICE_NAME = "NetworkService";
this.NETWORK_ERROR = 5000;
}
/**
@@ -46,9 +47,20 @@ class NetworkService {
operation
);
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) {
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
*/
async handleHttp(job) {
// Define operation for timing
const operation = async () => {
const response = await axios.get(job.data.url);
return response;
};
// attempt connection
try {
const { responseTime, response } = await this.measureResponseTime(
operation
);
// check if response is in the 200 range, if so, service is up
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) {
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.
* 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.
* @returns {Promise<boolean>} The status of the inserted check if successful, otherwise false.
*/
async logAndStoreCheck(job, isAlive, responseTime, error = null) {
const check = new Check({
monitorId: job.data._id,
status: isAlive,
responseTime,
statusCode: 0,
message: error ? error.message : "",
});
async logAndStoreCheck(check) {
try {
const insertedCheck = await check.save();
return insertedCheck.status;