mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
perf(medications): one compliance round trip and a memoised formatter hot path
Intl.DateTimeFormat instances are memoised per locale, timezone and options signature — construction dominated the 365-day ledger build and the hot path drops about fivefold. A batched GET /api/medications/compliance serves every card from one request through the same per-medication cache cells the detail page reads, replacing the per-card fan-out; the list response stays untouched so the due line never waits on a ledger build. The medications and compliance buckets serve stale-while-revalidate, interactive writes evict while background bulk sync marks stale, the per-id route defers ownership and schedule reads until a cache miss, and the card body reserves constant slots for the status and cycle lines so late data stops shifting the layout.
This commit is contained in:
1 parent
23f7c74c04
commit
b346e78cc7
36 files changed
+1453
-500
No files matched your search
@@ -507,6 +507,19 @@ const medicationComplianceResponse = z
|
||||
"Adherence read for a single medication. `compliance30` is the authoritative 30-day taken-vs-expected summary; `dailyCompliance` is the per-day grid for the history glyph track. The graded raw→week→month→year series used elsewhere for AI prompts does NOT apply here — this response is never downsampled.",
|
||||
});
|
||||
|
||||
const medicationComplianceSummaryEntry = z
|
||||
.object({
|
||||
medicationId: z.string(),
|
||||
compliance7: complianceResult,
|
||||
compliance30: complianceResult,
|
||||
complianceDisplay,
|
||||
})
|
||||
.meta({
|
||||
id: "MedicationComplianceSummaryEntry",
|
||||
description:
|
||||
"Compact per-medication adherence row for the batched card read: the 7-/30-day summaries plus the cadence-scaled display block. The per-day `dailyCompliance` grid is NOT on this shape — read the per-medication `/compliance` endpoint for the history glyph track.",
|
||||
});
|
||||
|
||||
// v1.16.5 — schedule-era management (the Zeitplan-tab history timeline).
|
||||
// Archived eras come from two provenances: the wholesale-replace write
|
||||
// path (`ARCHIVED`, immutable) and the user-entered pre-tracking flow
|
||||
@@ -856,6 +869,28 @@ export const medicationPaths: NonNullable<ZodOpenApiObject["paths"]> = {
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/medications/compliance": {
|
||||
get: {
|
||||
tags: ["Medications"],
|
||||
summary: "Batched adherence read for every medication of the caller",
|
||||
description:
|
||||
"Returns one compact adherence row per medication the caller owns (active + paused), ordered by `createdAt DESC` — the single round trip the medication cards consume instead of fanning out one `/api/medications/{id}/compliance` request per card. Each row carries the 7-/30-day summaries and the cadence-scaled display block; the per-day grid stays on the per-medication endpoint. Pure computation — no writes. Served through the same per-medication server cache as the per-id read, so the two endpoints warm each other.",
|
||||
responses: {
|
||||
"200": {
|
||||
description: "One adherence row per medication.",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: dataEnvelope(
|
||||
z.array(medicationComplianceSummaryEntry),
|
||||
"ListMedicationComplianceResponse",
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
...stdResponses,
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/medications/{id}/compliance": {
|
||||
get: {
|
||||
tags: ["Medications"],
|
||||
|
||||
Reference in new issue
Block a user