diff --git a/lib/employee-detail-data.ts b/lib/employee-detail-data.ts index 5b0e235..d2314a4 100644 --- a/lib/employee-detail-data.ts +++ b/lib/employee-detail-data.ts @@ -10,8 +10,13 @@ import { offeneStellenAbfrage, resolveOpenPositions, type OffeneStelle } from ". // // Vorher: die Person, dann acht Dinge in einem Promise.all, dann die Namen der // Beteiligten. Das Promise.all war keine Gleichzeitigkeit — eine Transaktion -// hängt an einer Verbindung (lib/db/json.ts). Bei rund 36 ms Umlaufzeit war -// diese Seite damit die teuerste der Anwendung. +// hängt an einer Verbindung (lib/db/json.ts). +// +// Hier stand „bei rund 36 ms Umlaufzeit". Nachgemessen sind es 0,5 ms; die +// Zahl der Rundreisen ist also nicht der Hebel, für den sie hier gehalten +// wurde. Teuer war die Akte aus einem anderen Grund — 1,5 s, davon 1,4 s in +// om_reporting_lines unter Zeilenschutz (siehe Migration 20260924220000). +// Jetzt liegt die ganze Seite bei rund 100 ms. // // Die drei Tabellen mit `selectAll()` stehen hier ausgeschrieben. Das ist // keine Umständlichkeit: innerhalb von JSON formatiert Postgres timestamptz @@ -19,21 +24,7 @@ import { offeneStellenAbfrage, resolveOpenPositions, type OffeneStelle } from ". // darüber, was später passiert ist. Ausgeschrieben ist sichtbar, welche Spalte // durch zeitstempel() geht — bei selectAll() wäre es unsichtbar falsch. -// ── Vorübergehende Messung ──────────────────────────────────────── -// -// Die Akte braucht beim Öffnen rund anderthalb Sekunden, und es ist unklar, -// wovon. Die Datenbank ist es dem Anschein nach nicht: eine Rundreise kostet -// 0,5 ms, om_reporting_lines 60 ms. Statt weiter zu raten, misst diese Zeile -// die drei Abschnitte und schreibt eine Zeile ins Protokoll des Containers. -// -// **Wieder entfernen**, sobald die Ursache feststeht. -function messen(id: string, marken: [string, number][]) { - const teile = marken.map(([name, ms]) => `${name} ${Math.round(ms)}ms`).join(", "); - console.info(`[Akte ${id.slice(0, 8)}] ${teile}`); -} - export async function loadEmployeeDetail(tx: Tx, id: string, today: string = todayIso()) { - const t0 = performance.now(); // Die Person zuerst, allein: erst aus Eintritt und Austritt ergibt sich der // Stichtag, zu dem ihre Organisation überhaupt eine Antwort hat. Eine // Person, die am 01.09. anfängt, hat heute keine laufende Besetzung — zu @@ -41,8 +32,6 @@ export async function loadEmployeeDetail(tx: Tx, id: string, today: string = tod // behauptete „Keine Führungskraft", obwohl das Team eine hat. const employee = await tx.selectFrom("employees").selectAll().where("id", "=", id).executeTakeFirst(); if (!employee) return null; - const t1 = performance.now(); - const asOf = orgAsOf(employee, today); const g = await tx @@ -136,8 +125,6 @@ export async function loadEmployeeDetail(tx: Tx, id: string, today: string = tod ]) .executeTakeFirstOrThrow(); - const t2 = performance.now(); - const orgMaps = buildOrgMaps(g.units as never, g.locations as never); const line = g.lines.find((l) => l.employee_id === id) ?? null; const reports = g.lines.filter((l) => l.acting_manager_id === id); @@ -164,15 +151,6 @@ export async function loadEmployeeDetail(tx: Tx, id: string, today: string = tod resolveOpenPositions(tx, orgMaps, g.open as OffeneStelle[], today), ]); - const t3 = performance.now(); - messen(id, [ - ["person", t1 - t0], - ["hauptabfrage", t2 - t1], - ["nachschlag", t3 - t2], - ["gesamt", t3 - t0], - ["zeilen", g.lines.length], - ]); - return { employee, line,