From c021d04f5372ffa754c425cab7a7e6753d0fd6e5 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 24 Jul 2026 11:09:53 -0700 Subject: [PATCH] extract swtich --- .../checks/check.repository.interface.ts | 10 +-- .../domain/checks/check.repository.mongo.ts | 77 ++++++------------- server/src/domain/checks/check.service.ts | 16 ++-- server/src/service/network/DNSProvider.ts | 3 +- server/src/service/network/DockerProvider.ts | 4 +- server/src/service/network/GameProvider.ts | 2 +- server/src/service/network/HttpProvider.ts | 3 +- server/src/service/network/PortProvider.ts | 3 +- .../src/service/network/WebSocketProvider.ts | 3 +- server/src/service/network/utils.ts | 3 - server/src/service/networkService.ts | 2 +- server/src/types/network.ts | 2 + .../test/unit/services/checkService.test.ts | 8 +- 13 files changed, 56 insertions(+), 80 deletions(-) diff --git a/server/src/domain/checks/check.repository.interface.ts b/server/src/domain/checks/check.repository.interface.ts index 8c921c843..2db5df712 100644 --- a/server/src/domain/checks/check.repository.interface.ts +++ b/server/src/domain/checks/check.repository.interface.ts @@ -8,7 +8,7 @@ import type { } from "@/domain/checks/check.type.js"; import type { MonitorType } from "@/domain/monitors/monitor.types.js"; import type { LatestChecksMap } from "@/domain/checks/check.repository.mongo.js"; -import { DateRange } from "@/types/query.js"; +import { CheckFilter, DateRange } from "@/types/query.js"; export interface IChecksRepository { // create @@ -21,18 +21,18 @@ export interface IChecksRepository { monitorId: string, sortOrder: string, dateRange: DateRange, - filter: string | undefined, page: number, rowsPerPage: number, - status: boolean | undefined + status: boolean | undefined, + filter?: CheckFilter ): Promise; findByTeamId( sortOrder: string, dateRange: DateRange, - filter: string | undefined, page: number, rowsPerPage: number, - teamId: string + teamId: string, + filter?: CheckFilter ): Promise; findLatestByMonitorIds(monitorIds: string[], options?: { limitPerMonitor?: number }): Promise; findByDateRangeAndMonitorId( diff --git a/server/src/domain/checks/check.repository.mongo.ts b/server/src/domain/checks/check.repository.mongo.ts index f07f7b3ee..4687f8ffc 100644 --- a/server/src/domain/checks/check.repository.mongo.ts +++ b/server/src/domain/checks/check.repository.mongo.ts @@ -20,8 +20,9 @@ import { ILogger } from "@/utils/logger.js"; import { toStringId, toDateString } from "@/utils/mongoMappers.js"; import { getHardwareUpChecks, getHardwareStats, getHardwareTotalChecks } from "@/domain/checks/check.hardware.aggregations.js"; -import { DateRange } from "@/types/query.js"; +import { CheckFilter, DateRange } from "@/types/query.js"; import { AppError } from "@/utils/AppError.js"; +import { NETWORK_ERROR } from "@/types/network.js"; const SERVICE_NAME = "StatusService"; @@ -211,46 +212,41 @@ class MongoChecksRepository implements IChecksRepository { return this.mapDocuments(inserted as unknown as CheckDocument[]); }; + private filterToMatch = (filter: CheckFilter | undefined): Record => { + switch (filter) { + case "up": + return { status: true }; + case "down": + return { status: false }; + case "resolve": + return { status: false, statusCode: NETWORK_ERROR }; + default: + this.logger.warn({ + message: "invalid filter", + service: SERVICE_NAME, + method: "filterToMatch", + }); + return {}; + } + }; + findByMonitorId = async ( monitorId: string, sortOrder: string, dateRange: DateRange, - filter: string | undefined, page: number, rowsPerPage: number, - status: boolean | undefined + status: boolean | undefined, + filter?: CheckFilter ) => { // Match const matchStage: Record = { "metadata.monitorId": new mongoose.Types.ObjectId(monitorId), ...(typeof status !== "undefined" && { status }), createdAt: { $gte: getDateForRange(dateRange) }, + ...this.filterToMatch(filter), }; - if (filter !== undefined) { - switch (filter) { - case "all": - break; - case "up": - matchStage.status = true; - break; - case "down": - matchStage.status = false; - break; - case "resolve": - matchStage.status = false; - matchStage.statusCode = 5000; - break; - default: - this.logger.warn({ - message: "invalid filter", - service: SERVICE_NAME, - method: "getChecks", - }); - break; - } - } - //Sort const convertedSortOrder = sortOrder === "asc" ? 1 : -1; @@ -268,35 +264,12 @@ class MongoChecksRepository implements IChecksRepository { return { checksCount, checks: this.mapDocuments(checks) }; }; - findByTeamId = async (sortOrder: string, dateRange: DateRange, filter: string, page: number, rowsPerPage: number, teamId: string) => { + findByTeamId = async (sortOrder: string, dateRange: DateRange, page: number, rowsPerPage: number, teamId: string, filter?: CheckFilter) => { const matchStage: Record = { "metadata.teamId": new mongoose.Types.ObjectId(teamId), createdAt: { $gte: getDateForRange(dateRange) }, + ...this.filterToMatch(filter), }; - // Add filter to match stage - if (filter !== undefined) { - switch (filter) { - case "all": - break; - case "up": - matchStage.status = true; - break; - case "down": - matchStage.status = false; - break; - case "resolve": - matchStage.status = false; - matchStage.statusCode = 5000; - break; - default: - this.logger.warn({ - message: "invalid filter", - service: SERVICE_NAME, - method: "getChecksByTeam", - }); - break; - } - } const parsedSortOrder = sortOrder === "asc" ? 1 : -1; diff --git a/server/src/domain/checks/check.service.ts b/server/src/domain/checks/check.service.ts index b577658bd..40dd88f80 100644 --- a/server/src/domain/checks/check.service.ts +++ b/server/src/domain/checks/check.service.ts @@ -6,7 +6,7 @@ import type { MonitorPayloadMap, MonitorStatusResponse } from "@/types/network.j import type { HardwareStatusPayload, PageSpeedStatusPayload } from "@/types/network.js"; import { AppError } from "@/utils/AppError.js"; import { ILogger } from "@/utils/logger.js"; -import { DateRange } from "@/types/query.js"; +import { CheckFilter, DateRange } from "@/types/query.js"; const SERVICE_NAME = "checkService"; @@ -22,7 +22,7 @@ export interface ICheckService { dateRange: DateRange; page: number; rowsPerPage: number; - filter?: string; + filter?: CheckFilter; status?: boolean; }): Promise; getChecksByTeam(params: { @@ -31,7 +31,7 @@ export interface ICheckService { dateRange: DateRange; page: number; rowsPerPage: number; - filter?: string; + filter?: CheckFilter; }): Promise; getChecksSummaryByTeamId(params: { teamId: string; dateRange: DateRange }): Promise; deleteChecks(params: { monitorId: string; teamId: string }): Promise; @@ -169,7 +169,7 @@ export class CheckService implements ICheckService { page: number; rowsPerPage: number; status?: boolean; - filter?: string; + filter: CheckFilter; }) => { if (!monitorId) { throw new AppError({ message: "No monitor ID in request", service: SERVICE_NAME, method: "getChecksByMonitor", status: 400 }); @@ -184,7 +184,7 @@ export class CheckService implements ICheckService { const parsedPage = page ?? 0; const parsedRowsPerPage = rowsPerPage ?? 5; - const result = await this.checksRepository.findByMonitorId(monitorId, sortOrder, dateRange, filter, parsedPage, parsedRowsPerPage, status); + const result = await this.checksRepository.findByMonitorId(monitorId, sortOrder, dateRange, parsedPage, parsedRowsPerPage, status, filter); return result; }; @@ -193,21 +193,21 @@ export class CheckService implements ICheckService { teamId, sortOrder, dateRange, - filter, page, rowsPerPage, + filter, }: { teamId: string; sortOrder: string; dateRange: DateRange; page: number; rowsPerPage: number; - filter?: string; + filter?: CheckFilter; }) => { const parsedPage = page ?? 0; const parsedRowsPerPage = rowsPerPage ?? 5; - const checkData = await this.checksRepository.findByTeamId(sortOrder, dateRange, filter, parsedPage, parsedRowsPerPage, teamId); + const checkData = await this.checksRepository.findByTeamId(sortOrder, dateRange, parsedPage, parsedRowsPerPage, teamId, filter); return checkData; }; diff --git a/server/src/service/network/DNSProvider.ts b/server/src/service/network/DNSProvider.ts index 1aeff7e14..ff136db0e 100644 --- a/server/src/service/network/DNSProvider.ts +++ b/server/src/service/network/DNSProvider.ts @@ -3,7 +3,8 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import type { Resolver } from "dns/promises"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR, timeRequest } from "@/service/network/utils.js"; +import { timeRequest } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; const SERVICE_NAME = "DNSProvider"; diff --git a/server/src/service/network/DockerProvider.ts b/server/src/service/network/DockerProvider.ts index 0cfb133af..5e5d7b630 100644 --- a/server/src/service/network/DockerProvider.ts +++ b/server/src/service/network/DockerProvider.ts @@ -4,8 +4,8 @@ import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { ILogger } from "@/utils/logger.js"; import { AppError } from "@/utils/AppError.js"; import Dockerode from "dockerode"; -import { NETWORK_ERROR, timeRequest } from "@/service/network/utils.js"; - +import { timeRequest } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; type DockerodeType = typeof Dockerode; const SERVICE_NAME = "DockerProvider"; diff --git a/server/src/service/network/GameProvider.ts b/server/src/service/network/GameProvider.ts index 4e063396d..1a07de791 100644 --- a/server/src/service/network/GameProvider.ts +++ b/server/src/service/network/GameProvider.ts @@ -3,7 +3,7 @@ import { GameStatusPayload, MonitorStatusResponse } from "@/types/network.js"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { GameDig } from "gamedig"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import { ILogger } from "@/utils/logger.js"; type GameDigType = typeof GameDig; diff --git a/server/src/service/network/HttpProvider.ts b/server/src/service/network/HttpProvider.ts index 2f08dab00..fb974cac1 100644 --- a/server/src/service/network/HttpProvider.ts +++ b/server/src/service/network/HttpProvider.ts @@ -6,7 +6,8 @@ import { MonitorStatusResponse } from "@/types/network.js"; import { Agent as HttpsAgent } from "https"; import { Agent as HttpAgent } from "http"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; -import { NETWORK_ERROR, isStatusUp } from "@/service/network/utils.js"; +import { isStatusUp } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import CacheableLookup from "cacheable-lookup"; export class HttpProvider implements IStatusProvider { diff --git a/server/src/service/network/PortProvider.ts b/server/src/service/network/PortProvider.ts index debcd8509..b59eb5907 100644 --- a/server/src/service/network/PortProvider.ts +++ b/server/src/service/network/PortProvider.ts @@ -2,7 +2,8 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { PortStatusPayload, MonitorStatusResponse } from "@/types/network.js"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR, timeRequest } from "@/service/network/utils.js"; +import { timeRequest } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import * as net from "net"; type NetType = typeof net; diff --git a/server/src/service/network/WebSocketProvider.ts b/server/src/service/network/WebSocketProvider.ts index fef5f76b1..b599e6fab 100644 --- a/server/src/service/network/WebSocketProvider.ts +++ b/server/src/service/network/WebSocketProvider.ts @@ -2,7 +2,8 @@ import { IStatusProvider } from "@/service/network/IStatusProvider.js"; import { WebSocketStatusPayload, MonitorStatusResponse } from "@/types/network.js"; import { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR, timeRequest } from "@/service/network/utils.js"; +import { timeRequest } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import type WebSocket from "ws"; type WebSocketConstructor = typeof WebSocket; diff --git a/server/src/service/network/utils.ts b/server/src/service/network/utils.ts index 8bcbc4335..5a23a9412 100644 --- a/server/src/service/network/utils.ts +++ b/server/src/service/network/utils.ts @@ -12,9 +12,6 @@ export const timeRequest = async (operation: () => Promise): Promise<{ res } }; -export const NETWORK_ERROR = 5000; -export const PING_ERROR = 5001; - export const isStatusUp = (statusCode: number | undefined, customUpCodes: HttpStatusCode[] = []): boolean => { if (statusCode === undefined) return false; return (statusCode >= 200 && statusCode < 300) || customUpCodes.includes(statusCode); diff --git a/server/src/service/networkService.ts b/server/src/service/networkService.ts index 632a03141..ec54b8e49 100644 --- a/server/src/service/networkService.ts +++ b/server/src/service/networkService.ts @@ -2,7 +2,7 @@ import type { Monitor, MonitorType } from "@/domain/monitors/monitor.types.js"; import type { MonitorPayloadMap, MonitorStatusResponse } from "@/types/network.js"; import type { AxiosStatic } from "axios"; import { AppError } from "@/utils/AppError.js"; -import { NETWORK_ERROR } from "@/service/network/utils.js"; +import { NETWORK_ERROR } from "@/types/network.js"; import { ILogger } from "@/utils/logger.js"; import { IStatusProvider } from "./network/IStatusProvider.js"; const SERVICE_NAME = "NetworkService"; diff --git a/server/src/types/network.ts b/server/src/types/network.ts index fe85221f2..b5dc1d949 100644 --- a/server/src/types/network.ts +++ b/server/src/types/network.ts @@ -13,6 +13,8 @@ import type { DnsRecordType, Monitor, MonitorMatchMethod, MonitorStatus, Monitor import type { QueryResult } from "gamedig"; +export const NETWORK_ERROR = 5000; + export interface MonitorStatusResponse< T = | HttpStatusPayload diff --git a/server/test/unit/services/checkService.test.ts b/server/test/unit/services/checkService.test.ts index 587731951..8c58259e3 100644 --- a/server/test/unit/services/checkService.test.ts +++ b/server/test/unit/services/checkService.test.ts @@ -375,7 +375,7 @@ describe("CheckService", () => { rowsPerPage: null as any, }); - expect(checksRepository.findByMonitorId).toHaveBeenCalledWith("mon-1", "desc", "day", undefined, 0, 5, undefined); + expect(checksRepository.findByMonitorId).toHaveBeenCalledWith("mon-1", "desc", "day", 0, 5, undefined, undefined); }); it("passes filter and status parameters", async () => { @@ -388,11 +388,11 @@ describe("CheckService", () => { dateRange: "week", page: 2, rowsPerPage: 20, - filter: "error", + filter: "resolve", status: false, }); - expect(checksRepository.findByMonitorId).toHaveBeenCalledWith("mon-1", "asc", "week", "error", 2, 20, false); + expect(checksRepository.findByMonitorId).toHaveBeenCalledWith("mon-1", "asc", "week", 2, 20, false, "resolve"); }); it("throws when monitorId is missing", async () => { @@ -443,7 +443,7 @@ describe("CheckService", () => { await service.getChecksByTeam({ teamId: "team-1", sortOrder: "desc", dateRange: "day", page: null as any, rowsPerPage: null as any }); - expect(checksRepository.findByTeamId).toHaveBeenCalledWith("desc", "day", undefined, 0, 5, "team-1"); + expect(checksRepository.findByTeamId).toHaveBeenCalledWith("desc", "day", 0, 5, "team-1", undefined); }); });