perf: batch-load app history to eliminate N+1 fetches on board load
Previously each AppWidget fetched /api/apps/{id}/history individually
on mount, causing N sequential HTTP requests. Now the board page
server load fetches all app histories in a single Prisma query via
getBatchStatusHistory() and passes them to AppWidget via Svelte
context. AppWidget uses the pre-loaded data immediately with a
fallback fetch for non-board contexts.
This commit is contained in:
@@ -75,7 +75,26 @@ export const load: PageServerLoad = async ({ params, locals }) => {
|
||||
}));
|
||||
}
|
||||
|
||||
return { board, canEdit, allApps, users, groups };
|
||||
// Batch-load sparkline history for all apps on this board (single query)
|
||||
const appIdsOnBoard = board.sections
|
||||
.flatMap((s: { widgets: { appId: string | null }[] }) => s.widgets)
|
||||
.map((w: { appId: string | null }) => w.appId)
|
||||
.filter((id: string | null): id is string => id !== null);
|
||||
|
||||
const historyMap = appIdsOnBoard.length > 0
|
||||
? await appService.getBatchStatusHistory(appIdsOnBoard)
|
||||
: new Map();
|
||||
|
||||
// Serialize the Map to a plain object for the client
|
||||
const appHistories: Record<string, { history: { status: string; responseTime: number | null; checkedAt: string }[]; uptimePercent: number }> = {};
|
||||
for (const [appId, data] of historyMap) {
|
||||
appHistories[appId] = {
|
||||
history: data.history.map((h) => ({ ...h, checkedAt: h.checkedAt.toISOString() })),
|
||||
uptimePercent: data.uptimePercent
|
||||
};
|
||||
}
|
||||
|
||||
return { board, canEdit, allApps, users, groups, appHistories };
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Board not found';
|
||||
if (message.includes('not found')) {
|
||||
|
||||
Reference in New Issue
Block a user