mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +00:00
v1.4.37.1 — event-loop unblock on the read path
Hotfix on top of v1.4.37. The post-deploy verify caught /api/analytics cold-mount hits of ~62 s and parallel /api/health checks of ~58 s on the live instance, far above the v1.4.37 1.5-3 s perf claim. Root cause: the synchronous ensureUserRollupsFresh(userId) call at the top of each heavy read path folds the trailing 90-day DAY window when the rollup watermark trails the newest measurement. On a power-user account whose iOS step samples push the watermark every few minutes, each cache miss synchronously paid the full refresh cost on a Node worker that also serves the rest of the request fan-out (including /api/health, /api/version, and concurrent iOS calls), and the event loop was blocked for the duration of the recompute. Convert the three call sites (analytics route, comprehensive aggregator, summaries slice) to fire-and-forget. The downstream probeRollupCoverage gate falls back to live SQL on partial coverage so correctness is preserved; the only user-observable change is one cache window of staleness on the very first request after a new measurement landed.
This commit is contained in:
1 parent
88028fa082
commit
98e078d359
7 files changed
+161
-22
No files matched your search
@@ -112,14 +112,18 @@ type AuthedUser = Awaited<ReturnType<typeof requireAuth>>["user"];
|
||||
* `buildCoachSnapshotImpl` shape.
|
||||
*/
|
||||
async function buildAnalyticsResponse(user: AuthedUser) {
|
||||
// v1.5.0 — warm the persistent rollup table as a side effect of
|
||||
// the analytics fan-out. No-op when rollups are already ahead of
|
||||
// the newest measurement; on first cold-mount after a process
|
||||
// restart it folds the trailing 90-day window so downstream
|
||||
// consumers (Coach drawer, weekly report, admin analytics) see a
|
||||
// warm rollup table on their next read. The route's response
|
||||
// shape is untouched.
|
||||
await ensureUserRollupsFresh(user.id);
|
||||
// v1.4.37.1 hotfix — fire-and-forget the rollup-fresh check.
|
||||
// Awaiting it on the read path can stall the Node event loop for
|
||||
// 30–60 s on a power-user account whose iOS step samples keep the
|
||||
// 90-day DAY window slightly stale, which starves /api/health,
|
||||
// /api/version, and concurrent iOS calls. The downstream coverage
|
||||
// probe falls back to live SQL when a type is uncovered, so
|
||||
// correctness is preserved; the worst the user sees is data from
|
||||
// up to ~60 s ago on the very first request after a fresh
|
||||
// measurement lands, and the next request returns the up-to-date
|
||||
// value once the background refresh completes. `ensureUserRollupsFresh`
|
||||
// wraps its own try/catch, so the void call cannot reject.
|
||||
void ensureUserRollupsFresh(user.id);
|
||||
|
||||
// v1.4.37 W2 — single per-type coverage probe shared by the
|
||||
// bp_in_target / healthScore / correlations branches below. The
|
||||
|
||||
Reference in new issue
Block a user