mirror of
https://github.com/fosrl/pangolin.git
synced 2026-07-26 15:19:57 +02:00
🚧 WIP: batched site status histories
This commit is contained in:
@@ -37,10 +37,11 @@ export async function getCachedStatusHistory(
|
||||
tzOffsetMinutes
|
||||
);
|
||||
const cached = await cache.get<StatusHistoryResponse>(cacheKey);
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
// if (cached !== undefined) {
|
||||
// return cached;
|
||||
// }
|
||||
|
||||
console.time(`[getCachedStatusHistory/${entityType}=${entityId}]`);
|
||||
// Anchor to local midnight (UTC when tzOffsetMinutes is 0) so the query
|
||||
// window aligns with stable calendar days for the requesting client
|
||||
const todayMidnightSec = localMidnightSec(tzOffsetMinutes);
|
||||
@@ -76,12 +77,14 @@ export async function getCachedStatusHistory(
|
||||
|
||||
const priorStatus = lastKnownEvent?.status ?? null;
|
||||
|
||||
console.time(`[computeBuckets/${entityType}=${entityId}]`);
|
||||
const { buckets, totalDowntime } = computeBuckets(
|
||||
events,
|
||||
days,
|
||||
priorStatus,
|
||||
tzOffsetMinutes
|
||||
);
|
||||
console.timeEnd(`[computeBuckets/${entityType}=${entityId}]`);
|
||||
const totalWindow = days * 86400;
|
||||
const overallUptime =
|
||||
totalWindow > 0
|
||||
@@ -96,6 +99,7 @@ export async function getCachedStatusHistory(
|
||||
totalDowntimeSeconds: totalDowntime
|
||||
};
|
||||
|
||||
console.timeEnd(`[getCachedStatusHistory/${entityType}=${entityId}]`);
|
||||
await cache.set(cacheKey, result, STATUS_HISTORY_CACHE_TTL);
|
||||
return result;
|
||||
}
|
||||
@@ -299,7 +303,6 @@ export function computeBuckets(
|
||||
status
|
||||
});
|
||||
}
|
||||
|
||||
return { buckets, totalDowntime };
|
||||
}
|
||||
|
||||
@@ -311,7 +314,8 @@ export type BatchedStatusHistoryResponse = Record<
|
||||
export async function getBatchedStatusHistory(
|
||||
entityType: string,
|
||||
entityIds: number[],
|
||||
days: number
|
||||
days: number,
|
||||
tzOffsetMinutes: number = 0
|
||||
): Promise<BatchedStatusHistoryResponse> {
|
||||
// const cacheKey = statusHistoryCacheKey(entityType, entityId, days);
|
||||
// const cached = await cache.get<StatusHistoryResponse>(cacheKey);
|
||||
@@ -319,10 +323,13 @@ export async function getBatchedStatusHistory(
|
||||
// return cached;
|
||||
// }
|
||||
|
||||
// Anchor to UTC midnight so the query window aligns with stable calendar days
|
||||
const utcToday = new Date();
|
||||
utcToday.setUTCHours(0, 0, 0, 0);
|
||||
const todayMidnightSec = Math.floor(utcToday.getTime() / 1000);
|
||||
console.time(
|
||||
`[getBatchedStatusHistory/${entityType}=(${entityIds.join(" ,")})]`
|
||||
);
|
||||
|
||||
// Anchor to local midnight (UTC when tzOffsetMinutes is 0) so the query
|
||||
// window aligns with stable calendar days for the requesting client
|
||||
const todayMidnightSec = localMidnightSec(tzOffsetMinutes);
|
||||
const startSec = todayMidnightSec - days * 86400;
|
||||
|
||||
const events = await logsDb
|
||||
@@ -337,6 +344,10 @@ export async function getBatchedStatusHistory(
|
||||
)
|
||||
.orderBy(asc(statusHistory.timestamp));
|
||||
|
||||
console.log({
|
||||
events
|
||||
});
|
||||
|
||||
// Fetch the last known state before the window so that entities that
|
||||
// haven't changed status recently still show the correct status rather
|
||||
// than appearing as "no_data".
|
||||
@@ -375,6 +386,7 @@ export async function getBatchedStatusHistory(
|
||||
|
||||
const result: BatchedStatusHistoryResponse = {};
|
||||
|
||||
console.time(`[computeBuckets/${entityType}=(${entityIds.join(" ,")})]`);
|
||||
for (const entityId in eventStatusMap) {
|
||||
const event = eventStatusMap[Number(entityId)];
|
||||
const priorStatus = event.lastKnownEvent?.status ?? null;
|
||||
@@ -401,7 +413,11 @@ export async function getBatchedStatusHistory(
|
||||
totalDowntimeSeconds: totalDowntime
|
||||
};
|
||||
}
|
||||
console.timeEnd(`[computeBuckets/${entityType}=(${entityIds.join(" ,")})]`);
|
||||
|
||||
console.timeEnd(
|
||||
`[getBatchedStatusHistory/${entityType}=(${entityIds.join(" ,")})]`
|
||||
);
|
||||
// await cache.set(cacheKey, result, STATUS_HISTORY_CACHE_TTL);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -319,6 +319,13 @@ authenticated.get(
|
||||
site.getSiteStatusHistory
|
||||
);
|
||||
|
||||
authenticated.get(
|
||||
"/org/:orgId/site-status-histories",
|
||||
verifyOrgAccess,
|
||||
verifyUserHasAction(ActionsEnum.listSites),
|
||||
site.getBatchedSiteStatusHistory
|
||||
);
|
||||
|
||||
// Site Resource endpoints
|
||||
authenticated.put(
|
||||
"/org/:orgId/site-resource",
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { z } from "zod";
|
||||
import response from "@server/lib/response";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
import createHttpError from "http-errors";
|
||||
import logger from "@server/logger";
|
||||
import { fromError } from "zod-validation-error";
|
||||
import {
|
||||
getCachedStatusHistory,
|
||||
statusHistoryQuerySchema,
|
||||
StatusHistoryResponse
|
||||
getBatchedStatusHistory,
|
||||
type BatchedStatusHistoryResponse
|
||||
} from "@server/lib/statusHistory";
|
||||
import logger from "@server/logger";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import createHttpError from "http-errors";
|
||||
import { z } from "zod";
|
||||
import { fromError } from "zod-validation-error";
|
||||
|
||||
const siteIdParamsSchema = z.object({
|
||||
days: z
|
||||
@@ -59,12 +58,16 @@ export async function getBatchedSiteStatusHistory(
|
||||
}
|
||||
|
||||
const entityType = "site";
|
||||
const entityId = parsedParams.data.siteId;
|
||||
const { days } = parsedQuery.data;
|
||||
const { days, siteIds, tzOffsetMinutes } = parsedQuery.data;
|
||||
|
||||
const data = await getCachedStatusHistory(entityType, entityId, days);
|
||||
const data = await getBatchedStatusHistory(
|
||||
entityType,
|
||||
siteIds,
|
||||
days,
|
||||
tzOffsetMinutes
|
||||
);
|
||||
|
||||
return response<StatusHistoryResponse>(res, {
|
||||
return response<BatchedStatusHistoryResponse>(res, {
|
||||
data,
|
||||
success: true,
|
||||
error: false,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from "./getSite";
|
||||
export * from "./getStatusHistory";
|
||||
export * from "./getBatchedStatusHistory";
|
||||
export * from "./createSite";
|
||||
export * from "./deleteSite";
|
||||
export * from "./updateSite";
|
||||
|
||||
Reference in New Issue
Block a user