From 3b858de2b5c9c573ca7e0f87a2ea960a0a758094 Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Fri, 20 Feb 2026 00:56:54 -0500 Subject: [PATCH] feat: add buffer lookup and location results update to services ## Changes - Add findInBuffer() to BufferService for looking up checks still in the write buffer - Add updateLocationResults() to IChecksRepository interface and MongoChecksRepository - Update GlobalpingService to return GlobalpingCheckResult[] instead of MonitorStatusResponse[] ## Benefits Non-destructive service additions that prepare the backfill pipeline. Existing check-writing and Globalping flows are unchanged. --- .../repositories/checks/IChecksRepository.ts | 2 ++ .../checks/MongoChecksRepistory.ts | 5 +++++ .../service/infrastructure/bufferService.ts | 5 +++++ .../infrastructure/globalpingService.ts | 22 +++++++------------ 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/server/src/repositories/checks/IChecksRepository.ts b/server/src/repositories/checks/IChecksRepository.ts index 60e7aab06..dffd7e13c 100644 --- a/server/src/repositories/checks/IChecksRepository.ts +++ b/server/src/repositories/checks/IChecksRepository.ts @@ -2,6 +2,7 @@ import type { Check, ChecksQueryResult, ChecksSummary, + LocationResult, MonitorType, PageSpeedChecksResult, HardwareChecksResult, @@ -37,6 +38,7 @@ export interface IChecksRepository { findSummaryByTeamId(teamId: string, dateRange: string): Promise; findLocationChecksByMonitorId(monitorId: string, startDate: Date, endDate: Date, dateString: string): Promise>; // update + updateLocationResults(checkId: string, locationResults: LocationResult[]): Promise; //delete deleteByMonitorId(monitorId: string): Promise; deleteByTeamId(teamId: string): Promise; diff --git a/server/src/repositories/checks/MongoChecksRepistory.ts b/server/src/repositories/checks/MongoChecksRepistory.ts index b1e5d4059..ccd17b4a5 100644 --- a/server/src/repositories/checks/MongoChecksRepistory.ts +++ b/server/src/repositories/checks/MongoChecksRepistory.ts @@ -11,6 +11,7 @@ import type { CheckMetadata, CheckNetworkInterfaceInfo, GotTimings, + LocationResult, MonitorType, } from "@/types/index.js"; import { CheckModel, MonitorModel, type CheckDocument } from "@/db/models/index.js"; @@ -406,6 +407,10 @@ class MongoChecksRepository implements IChecksRepository { }; }; + updateLocationResults = async (checkId: string, locationResults: LocationResult[]): Promise => { + await CheckModel.updateOne({ _id: new mongoose.Types.ObjectId(checkId) }, { $set: { locationResults } }); + }; + deleteByMonitorId = async (monitorId: string): Promise => { const result = await CheckModel.deleteMany({ "metadata.monitorId": new mongoose.Types.ObjectId(monitorId) }); return result.deletedCount; diff --git a/server/src/service/infrastructure/bufferService.ts b/server/src/service/infrastructure/bufferService.ts index c38fd52a4..0297e10d0 100755 --- a/server/src/service/infrastructure/bufferService.ts +++ b/server/src/service/infrastructure/bufferService.ts @@ -5,6 +5,7 @@ const SERVICE_NAME = "BufferService"; export interface IBufferService { addToBuffer(check: Check): void; removeCheckFromBuffer(check: Check): boolean; + findInBuffer(checkId: string): Check | undefined; scheduleNextFlush(): void; flushBuffer(): Promise; } @@ -49,6 +50,10 @@ class BufferService implements IBufferService { } } + findInBuffer(checkId: string): Check | undefined { + return this.buffer.find((c: Check) => c.id?.toString() === checkId); + } + removeCheckFromBuffer(checkToRemove: Check) { try { if (!checkToRemove) { diff --git a/server/src/service/infrastructure/globalpingService.ts b/server/src/service/infrastructure/globalpingService.ts index 935177e61..f33cd8f26 100644 --- a/server/src/service/infrastructure/globalpingService.ts +++ b/server/src/service/infrastructure/globalpingService.ts @@ -1,7 +1,7 @@ import { Globalping } from "globalping"; import type { ISettingsService } from "@/service/system/settingsService.js"; import type { Monitor } from "@/types/monitor.js"; -import type { MonitorStatusResponse } from "@/types/network.js"; +import type { GlobalpingCheckResult } from "@/types/network.js"; const SERVICE_NAME = "GlobalpingService"; @@ -130,7 +130,7 @@ class GlobalpingService { return { client: this.client, locationIds }; } - async runChecks(monitor: Monitor): Promise { + async runChecks(monitor: Monitor): Promise { if (monitor.type !== "http" && monitor.type !== "ping") { return []; } @@ -148,7 +148,7 @@ class GlobalpingService { } } - private async executeChecks(monitor: Monitor): Promise { + private async executeChecks(monitor: Monitor): Promise { const { client, locationIds } = await this.getClientAndLocations(); if (!client || locationIds.length === 0) { return []; @@ -224,7 +224,7 @@ class GlobalpingService { } const measurement = awaitResult.data as any; - const results: MonitorStatusResponse[] = []; + const results: GlobalpingCheckResult[] = []; for (const item of measurement.results || []) { const probe = item.probe; @@ -233,27 +233,21 @@ class GlobalpingService { if (measurementType === "http") { results.push({ - monitorId: monitor.id, - teamId: monitor.teamId, - type: monitor.type, + location: locationId, status: result.statusCode >= 200 && result.statusCode < 400, - code: result.statusCode || 0, + statusCode: result.statusCode || 0, message: result.statusCodeName || result.rawOutput || "", responseTime: result.timings?.total ?? 0, - location: locationId, }); } else { // Ping: loss < 100% is considered up (consistent with local ping checks) const stats = result.stats; results.push({ - monitorId: monitor.id, - teamId: monitor.teamId, - type: monitor.type, + location: locationId, status: stats?.loss !== undefined ? stats.loss < 100 : false, - code: stats?.loss === 0 ? 200 : 5000, + statusCode: stats?.loss === 0 ? 200 : 5000, message: stats?.loss === 0 ? "Ping successful" : `Packet loss: ${stats?.loss}%`, responseTime: stats?.avg ?? 0, - location: locationId, }); } }