Skip to content

Commit d40b766

Browse files
committed
timescaleDB implementation
1 parent 7547d1d commit d40b766

1 file changed

Lines changed: 50 additions & 1 deletion

File tree

server/src/repositories/monitors/TimescaleMonitorsRepository.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Pool } from "pg";
2-
import type { Monitor, MonitorsSummary, MonitorStatus, MonitorType, MonitorMatchMethod, GeoContinent } from "@/types/monitor.js";
2+
import type { Monitor, MonitorsSummary, MonitorStatus, MonitorType, MonitorMatchMethod, GeoContinent, CheckSnapshot } from "@/types/monitor.js";
33
import type { IMonitorsRepository, TeamQueryConfig, SummaryConfig } from "./IMonitorsRepository.js";
44
import { AppError } from "@/utils/AppError.js";
55

@@ -641,6 +641,55 @@ export class TimescaleMonitorsRepository implements IMonitorsRepository {
641641
return entity;
642642
};
643643

644+
updateStatusWindowAndChecks = async (
645+
monitorId: string,
646+
teamId: string,
647+
status: boolean,
648+
_checkSnapshot: CheckSnapshot,
649+
windowSize: number,
650+
_maxRecentChecks: number,
651+
statusPatch?: Partial<Monitor>
652+
): Promise<Monitor> => {
653+
// In TimescaleDB, recentChecks live in the checks table (inserted by the buffer service),
654+
// so we only need to atomically update status_window and any statusPatch fields.
655+
const sets: string[] = [
656+
`status_window = (array_append(COALESCE(status_window, ARRAY[]::boolean[]), $1))[array_length(array_append(COALESCE(status_window, ARRAY[]::boolean[]), $1), 1) - $2 + 1:]`,
657+
`updated_at = NOW()`,
658+
];
659+
const values: unknown[] = [status, windowSize];
660+
let paramIndex = 3;
661+
662+
if (statusPatch) {
663+
const patchFieldMap: [keyof Monitor, string][] = [
664+
["status", "status"],
665+
["cpuAlertCounter", "cpu_alert_counter"],
666+
["memoryAlertCounter", "memory_alert_counter"],
667+
["diskAlertCounter", "disk_alert_counter"],
668+
["tempAlertCounter", "temp_alert_counter"],
669+
];
670+
for (const [key, column] of patchFieldMap) {
671+
if (statusPatch[key] !== undefined) {
672+
sets.push(`${column} = $${paramIndex++}`);
673+
values.push(statusPatch[key]);
674+
}
675+
}
676+
}
677+
678+
values.push(monitorId, teamId);
679+
const result = await this.pool.query<MonitorRow>(
680+
`UPDATE monitors SET ${sets.join(", ")} WHERE id = $${paramIndex++} AND team_id = $${paramIndex}
681+
RETURNING ${MONITOR_COLUMNS}`,
682+
values
683+
);
684+
const row = result.rows[0];
685+
if (!row) {
686+
throw new AppError({ message: `Failed to update status and checks for monitor with id ${monitorId}`, status: 500 });
687+
}
688+
const entity = this.toEntity(row);
689+
entity.notifications = await this.fetchNotificationIds([monitorId]).then((m) => m.get(monitorId) ?? []);
690+
return entity;
691+
};
692+
644693
togglePauseById = async (monitorId: string, teamId: string): Promise<Monitor> => {
645694
const result = await this.pool.query<MonitorRow>(
646695
`UPDATE monitors SET

0 commit comments

Comments
 (0)