diff --git a/server/src/db/models/GeoCheck.ts b/server/src/db/models/GeoCheck.ts index 689130f20..8c0749f00 100644 --- a/server/src/db/models/GeoCheck.ts +++ b/server/src/db/models/GeoCheck.ts @@ -106,9 +106,7 @@ const GeoCheckSchema = new Schema( GeoCheckSchema.index({ "metadata.monitorId": 1, createdAt: -1 }); GeoCheckSchema.index({ "metadata.monitorId": 1, createdAt: 1 }); -GeoCheckSchema.index({ "metadata.monitorId": 1, "results.location.continent": 1, createdAt: -1 }); GeoCheckSchema.index({ "metadata.teamId": 1, createdAt: -1 }); -GeoCheckSchema.index({ "metadata.teamId": 1, "results.status": 1, createdAt: -1 }); GeoCheckSchema.index({ createdAt: 1 }); const GeoCheckModel = model("GeoCheck", GeoCheckSchema); diff --git a/server/src/service/infrastructure/bufferService.ts b/server/src/service/infrastructure/bufferService.ts index 9870ae783..a32a57dde 100755 --- a/server/src/service/infrastructure/bufferService.ts +++ b/server/src/service/infrastructure/bufferService.ts @@ -1,5 +1,6 @@ import type { Check } from "@/types/index.js"; import type { GeoCheck } from "@/types/index.js"; +import type Logger from "@/utils/logger.js"; const SERVICE_NAME = "BufferService"; @@ -9,12 +10,13 @@ export interface IBufferService { removeCheckFromBuffer(check: Check): boolean; scheduleNextFlush(): void; flushBuffer(): Promise; + flushGeoBuffer(): Promise; } class BufferService implements IBufferService { static SERVICE_NAME = SERVICE_NAME; private BUFFER_TIMEOUT: number; - private logger: any; + private logger: Logger; private SERVICE_NAME: string; private buffer: any[]; private geoBuffer: any[]; @@ -28,7 +30,7 @@ class BufferService implements IBufferService { geoChecksService, settingsService, }: { - logger: any; + logger: Logger; checkService: any; geoChecksService?: any; settingsService: any; @@ -123,6 +125,7 @@ class BufferService implements IBufferService { this.bufferTimer = setTimeout(async () => { try { await this.flushBuffer(); + await this.flushGeoBuffer(); } catch (error: any) { this.logger.error({ message: `Error in flush cycle: ${error.message}`, @@ -139,23 +142,47 @@ class BufferService implements IBufferService { async flushBuffer() { try { if (this.buffer.length > 0) { + this.logger.debug({ + message: `Flushing ${this.buffer.length} checks to database`, + service: this.SERVICE_NAME, + method: "flushBuffer", + }); await this.checksService.createChecks(this.buffer); - } - - if (this.geoBuffer.length > 0 && this.geoChecksService) { - await this.geoChecksService.createGeoChecks(this.geoBuffer); + this.buffer = []; } } catch (error: any) { this.logger.error({ - message: error.message, + message: `Error flushing checks buffer: ${error.message}`, service: this.SERVICE_NAME, method: "flushBuffer", stack: error.stack, }); + // Clear buffer even on error to prevent infinite retry loops + this.buffer = []; } + } - this.buffer = []; - this.geoBuffer = []; + async flushGeoBuffer() { + try { + if (this.geoBuffer.length > 0) { + this.logger.debug({ + message: `Flushing ${this.geoBuffer.length} geo checks to database`, + service: this.SERVICE_NAME, + method: "flushGeoBuffer", + }); + await this.geoChecksService.createGeoChecks(this.geoBuffer); + this.geoBuffer = []; + } + } catch (error: any) { + this.logger.error({ + message: `Error flushing geo checks buffer: ${error.message}`, + service: this.SERVICE_NAME, + method: "flushGeoBuffer", + stack: error.stack, + }); + // Clear buffer even on error to prevent infinite retry loops + this.geoBuffer = []; + } } } diff --git a/server/src/service/infrastructure/globalPingService.ts b/server/src/service/infrastructure/globalPingService.ts index 3b6244849..720eb246a 100644 --- a/server/src/service/infrastructure/globalPingService.ts +++ b/server/src/service/infrastructure/globalPingService.ts @@ -1,4 +1,5 @@ import type { GeoContinent, GeoCheckResult, GeoCheckTimings, GeoCheckLocation } from "@/types/geoCheck.js"; +import type Logger from "@/utils/logger.js"; import got from "got"; const SERVICE_NAME = "GlobalPingService"; @@ -56,9 +57,9 @@ export interface IGlobalPingService { class GlobalPingService implements IGlobalPingService { static SERVICE_NAME = SERVICE_NAME; - private logger: any; + private logger: Logger; - constructor({ logger }: { logger: any }) { + constructor({ logger }: { logger: Logger }) { this.logger = logger; } @@ -68,9 +69,12 @@ class GlobalPingService implements IGlobalPingService { async createMeasurement(url: string, locations: GeoContinent[]): Promise { try { + // GlobalPing API expects target without protocol (http:// or https://) + const cleanTarget = url.replace(/^https?:\/\//, ""); + const requestBody: GlobalPingMeasurementRequest = { type: "http", - target: url, + target: cleanTarget, locations: locations.map((continent) => ({ continent })), limit: locations.length, }; @@ -96,7 +100,7 @@ class GlobalPingService implements IGlobalPingService { message: "GlobalPing API unavailable, skipping geo check", service: SERVICE_NAME, method: "createMeasurement", - details: error.message, + details: error, }); return null; }