implement remaining check methods

This commit is contained in:
Alex Holliday committed 2026-01-20 21:18:26 +00:00
1 parent 9af25a19e5
commit 27dea6a08e
8 files changed
+138 -339

No files matched your search

-247
View File
@@ -1,247 +0,0 @@
import { ObjectId } from "mongodb";
import mongoose from "mongoose";
import { CheckModel } from "@/db/models/index.js";
import { buildChecksSummaryByTeamIdPipeline } from "./checkModuleQueries.js";
const SERVICE_NAME = "checkModule";
const dateRangeLookup = {
recent: new Date(new Date().setDate(new Date().getDate() - 2)),
hour: new Date(new Date().setHours(new Date().getHours() - 1)),
day: new Date(new Date().setDate(new Date().getDate() - 1)),
week: new Date(new Date().setDate(new Date().getDate() - 7)),
month: new Date(new Date().setMonth(new Date().getMonth() - 1)),
all: undefined,
};
class CheckModule {
constructor({ logger, Monitor, User }) {
this.logger = logger;
this.Monitor = Monitor;
this.User = User;
}
getChecksByMonitor = async ({ monitorId, sortOrder, dateRange, filter, page, rowsPerPage, status }) => {
try {
status = status === "true" ? true : status === "false" ? false : undefined;
page = parseInt(page);
rowsPerPage = parseInt(rowsPerPage);
// Match
const matchStage = {
"metadata.monitorId": new ObjectId(monitorId),
...(typeof status !== "undefined" && { status }),
...(dateRangeLookup[dateRange] && {
createdAt: {
$gte: dateRangeLookup[dateRange],
},
}),
};
if (filter !== undefined) {
switch (filter) {
case "all":
break;
case "down":
break;
case "resolve":
matchStage.statusCode = 5000;
break;
default:
this.logger.warn({
message: "invalid filter",
service: SERVICE_NAME,
method: "getChecks",
});
break;
}
}
//Sort
sortOrder = sortOrder === "asc" ? 1 : -1;
// Pagination
let skip = 0;
if (page && rowsPerPage) {
skip = page * rowsPerPage;
}
const checks = await CheckModel.aggregate([
{ $match: matchStage },
{ $sort: { createdAt: sortOrder } },
{
$facet: {
summary: [{ $count: "checksCount" }],
checks: [{ $skip: skip }, { $limit: rowsPerPage }],
},
},
{
$project: {
checksCount: {
$ifNull: [{ $arrayElemAt: ["$summary.checksCount", 0] }, 0],
},
checks: {
$ifNull: ["$checks", []],
},
},
},
]);
return checks[0];
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getChecks";
throw error;
}
};
getChecksByTeam = async ({ sortOrder, dateRange, filter, page, rowsPerPage, teamId }) => {
try {
console.log({
sortOrder,
dateRange,
filter,
page,
rowsPerPage,
teamId,
});
page = parseInt(page);
rowsPerPage = parseInt(rowsPerPage);
const matchStage = {
"metadata.teamId": new ObjectId(teamId),
status: false,
...(dateRangeLookup[dateRange] && {
createdAt: {
$gte: dateRangeLookup[dateRange],
},
}),
};
// Add filter to match stage
if (filter !== undefined) {
switch (filter) {
case "all":
break;
case "down":
break;
case "resolve":
matchStage.statusCode = 5000;
break;
default:
this.logger.warn({
message: "invalid filter",
service: SERVICE_NAME,
method: "getChecksByTeam",
});
break;
}
}
sortOrder = sortOrder === "asc" ? 1 : -1;
// pagination
let skip = 0;
if (page && rowsPerPage) {
skip = page * rowsPerPage;
}
const aggregatePipeline = [
{ $match: matchStage },
{ $sort: { createdAt: sortOrder } },
{
$facet: {
summary: [{ $count: "checksCount" }],
checks: [{ $skip: skip }, { $limit: rowsPerPage }],
},
},
{
$project: {
checksCount: { $arrayElemAt: ["$summary.checksCount", 0] },
checks: "$checks",
},
},
];
const checks = await CheckModel.aggregate(aggregatePipeline);
return checks[0];
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getChecksByTeam";
throw error;
}
};
getChecksSummaryByTeamId = async ({ teamId }) => {
try {
const matchStage = {
"metadata.teamId": new ObjectId(teamId),
};
const checks = await CheckModel.aggregate(buildChecksSummaryByTeamIdPipeline({ matchStage }));
return checks[0].summary;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getChecksSummaryByTeamId";
throw error;
}
};
deleteChecks = async (monitorId) => {
try {
const result = await CheckModel.deleteMany({ "metadata.monitorId": monitorId });
return result.deletedCount;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "deleteChecks";
throw error;
}
};
deleteChecksByTeamId = async (teamId) => {
try {
// Find all monitor IDs for this team (only get _id field for efficiency)
const teamMonitors = await this.Monitor.find({ teamId }, { _id: 1 });
const monitorIds = teamMonitors.map((monitor) => monitor._id);
// Delete all checks for these monitors in one operation
const deleteResult = await CheckModel.deleteMany({ "metadata.monitorId": { $in: monitorIds } });
return deleteResult.deletedCount;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "deleteChecksByTeamId";
throw error;
}
};
updateChecksTTL = async (teamId, ttl) => {
try {
await CheckModel.collection.dropIndex("expiry_1");
} catch (error) {
this.logger.error({
message: error.message,
service: SERVICE_NAME,
method: "updateChecksTTL",
stack: error.stack,
});
}
try {
await CheckModel.collection.createIndex(
{ expiry: 1 },
{ expireAfterSeconds: ttl, partialFilterExpression: { "metadata.mode": { $exists: true } } }
);
} catch (error) {
error.service = SERVICE_NAME;
error.method = "updateChecksTTL";
throw error;
}
// Update user
try {
await this.User.updateMany({ teamId: teamId }, { checkTTL: ttl });
} catch (error) {
error.service = SERVICE_NAME;
error.method = "updateChecksTTL";
throw error;
}
};
}
export default CheckModule;
@@ -1,44 +0,0 @@
const buildChecksSummaryByTeamIdPipeline = ({ matchStage }) => {
return [
{ $match: matchStage },
{
$facet: {
summary: [
{
$group: {
_id: null,
totalChecks: { $sum: { $cond: [{ $eq: ["$status", false] }, 1, 0] } },
resolvedChecks: {
$sum: {
$cond: [{ $and: [{ $eq: ["$ack", true] }, { $eq: ["$status", false] }] }, 1, 0],
},
},
downChecks: {
$sum: {
$cond: [{ $and: [{ $eq: ["$ack", false] }, { $eq: ["$status", false] }] }, 1, 0],
},
},
cannotResolveChecks: {
$sum: {
$cond: [{ $eq: ["$statusCode", 5000] }, 1, 0],
},
},
},
},
{
$project: {
_id: 0,
},
},
],
},
},
{
$project: {
summary: { $arrayElemAt: ["$summary", 0] },
},
},
];
};
export { buildChecksSummaryByTeamIdPipeline };