From 9093e0fe51fd40f1a4700cc1bccad3c8589f4587 Mon Sep 17 00:00:00 2001 From: Alexander Bocken Date: Tue, 21 Apr 2026 07:36:55 +0200 Subject: [PATCH] perf: add Server-Timing, split fitness bundle, tighten DB queries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `timing` handle in hooks.server.ts emitting Server-Timing headers and expose `locals.timing.mark/measure` for per-load instrumentation. - Drop dead `getEnrichedExerciseById` fallback in fitness detail page — server load already 404s via errorWithVerse, so the client no longer pulls exercisedb-raw.json (~760KB) into the detail bundle. - Add `{ createdBy: 1, nextExecutionDate: -1 }` index on RecurringPayment for user-scoped list queries. - Narrow populate projections in cospend/debts (title/date/category on userSplits, _id only on allRelatedSplits) to cut payload + hydration. - Parallelize today's sessions + WorkoutSchedule lookup in the nutrition page load via Promise.all; add `.lean()` + `.select('templateId')` to the lastScheduled query. --- package.json | 2 +- src/app.d.ts | 4 +++ src/hooks.server.ts | 28 ++++++++++++++++++- src/models/RecurringPayment.ts | 1 + src/routes/api/cospend/debts/+server.ts | 4 +-- .../[id]/+page.svelte | 4 +-- .../[[date=fitnessDate]]/+page.server.ts | 14 ++++++---- 7 files changed, 44 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index f69ee3c8..a8884696 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.37.2", + "version": "1.37.3", "private": true, "type": "module", "scripts": { diff --git a/src/app.d.ts b/src/app.d.ts index cc6b1aba..c5eccc10 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -13,6 +13,10 @@ declare global { interface Locals { auth(): Promise; session?: Session | null; + timing: { + mark(name: string, dur: number): void; + measure(name: string, fn: () => Promise | T): Promise; + }; } // interface PageData {} interface PageState { diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 498bad61..f21c8848 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -6,6 +6,31 @@ import { initializeScheduler } from "./lib/server/scheduler" import { dbConnect } from "./utils/db" import { errorWithVerse, getRandomVerse } from "$lib/server/errorQuote" +async function timing({ event, resolve }: Parameters[0]) { + const marks: Record = {}; + event.locals.timing = { + mark(name, dur) { + marks[name] = (marks[name] ?? 0) + dur; + }, + async measure(name, fn) { + const t0 = performance.now(); + try { + return await fn(); + } finally { + this.mark(name, performance.now() - t0); + } + } + }; + const t0 = performance.now(); + const response = await resolve(event); + marks.total = performance.now() - t0; + const header = Object.entries(marks) + .map(([k, v]) => `${k};dur=${v.toFixed(1)}`) + .join(', '); + response.headers.set('Server-Timing', header); + return response; +} + // Initialize database connection on server startup console.log('🚀 Server starting - initializing database connection...'); await dbConnect().then(() => { @@ -19,7 +44,7 @@ await dbConnect().then(() => { }); async function authorization({ event, resolve }: Parameters[0]) { - const session = await event.locals.auth(); + const session = await event.locals.timing.measure('auth', () => event.locals.auth()); event.locals.session = session; const { fetch, url } = event; @@ -107,6 +132,7 @@ export const handleError: HandleServerError = async ({ error, event, status, mes }; export const handle: Handle = sequence( + timing, auth.handle, authorization ); diff --git a/src/models/RecurringPayment.ts b/src/models/RecurringPayment.ts index ba57c8df..f913c0eb 100644 --- a/src/models/RecurringPayment.ts +++ b/src/models/RecurringPayment.ts @@ -137,5 +137,6 @@ const RecurringPaymentSchema = new mongoose.Schema( // Index for efficiently finding payments that need to be executed RecurringPaymentSchema.index({ nextExecutionDate: 1, isActive: 1 }); +RecurringPaymentSchema.index({ createdBy: 1, nextExecutionDate: -1 }); export const RecurringPayment = mongoose.model("RecurringPayment", RecurringPaymentSchema); \ No newline at end of file diff --git a/src/routes/api/cospend/debts/+server.ts b/src/routes/api/cospend/debts/+server.ts index 05e457d5..fc237bf8 100644 --- a/src/routes/api/cospend/debts/+server.ts +++ b/src/routes/api/cospend/debts/+server.ts @@ -31,7 +31,7 @@ export const GET: RequestHandler = async ({ locals }) => { try { // Get all splits for the current user const userSplits = await PaymentSplit.find({ username: currentUser }) - .populate('paymentId') + .populate('paymentId', 'title date category _id') .lean(); // Get all other users who have splits with payments involving the current user @@ -40,7 +40,7 @@ export const GET: RequestHandler = async ({ locals }) => { paymentId: { $in: paymentIds } as any, username: { $ne: currentUser } }) - .populate('paymentId') + .populate('paymentId', '_id') .lean(); // Group debts by user diff --git a/src/routes/fitness/[exercises=fitnessExercises]/[id]/+page.svelte b/src/routes/fitness/[exercises=fitnessExercises]/[id]/+page.svelte index 016a788f..c9aab4b5 100644 --- a/src/routes/fitness/[exercises=fitnessExercises]/[id]/+page.svelte +++ b/src/routes/fitness/[exercises=fitnessExercises]/[id]/+page.svelte @@ -1,6 +1,5 @@