From a33de8268b87ae21c4a35cb87fecba81d5afa43f Mon Sep 17 00:00:00 2001 From: Fred KISSIE Date: Wed, 22 Jul 2026 19:32:53 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Get=20last=20known=20events=20wo?= =?UTF-8?q?rking=20with=20sqlite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/lib/statusHistory.ts | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/server/lib/statusHistory.ts b/server/lib/statusHistory.ts index da579d3d3..ecb3f369e 100644 --- a/server/lib/statusHistory.ts +++ b/server/lib/statusHistory.ts @@ -1,6 +1,6 @@ import { z } from "zod"; import { db, logsDb, statusHistory } from "@server/db"; -import { and, eq, gte, lt, asc, desc, inArray } from "drizzle-orm"; +import { and, eq, gte, lt, asc, desc, inArray, max, sql } from "drizzle-orm"; import { regionalCache as cache } from "#dynamic/lib/cache"; const STATUS_HISTORY_CACHE_TTL = 60; // seconds @@ -347,8 +347,26 @@ export async function getBatchedStatusHistory( // 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". - const lastKnownEvents = await logsDb - .selectDistinctOn([statusHistory.entityId, statusHistory.timestamp]) + + /** + * If we used only postgres, we would have used `SELECT DISTINCT ON` to get the + * latest event for each `entityId`, + * but it doesn't work on SQLite, so instead we use a subquery, + * the `ROW_NUMBER() OVER PARTITION` allows to assign a number + * to each row ordered by the timestamp, the number 1 is the first one appearing in + * the specified order, then the next and more, we only want the highest timestamp, + * so we get for `row_number=1` + */ + const lastKnowEventsSub = logsDb + .select({ + entityId: statusHistory.entityId, + status: statusHistory.status, + timestamp: statusHistory.timestamp, + row_number: + sql`ROW_NUMBER() OVER (PARTITION BY ${statusHistory.entityId} ORDER BY ${statusHistory.timestamp} DESC)`.as( + "row_number" + ) + }) .from(statusHistory) .where( and( @@ -357,7 +375,16 @@ export async function getBatchedStatusHistory( lt(statusHistory.timestamp, startSec) ) ) - .orderBy(desc(statusHistory.timestamp)); + .as("sub"); + + const lastKnownEvents = await logsDb + .select({ + entityId: lastKnowEventsSub.entityId, + status: lastKnowEventsSub.status, + timestamp: lastKnowEventsSub.timestamp + }) + .from(lastKnowEventsSub) + .where(eq(lastKnowEventsSub.row_number, 1)); const eventStatusMap: Record< number,