mirror of
https://github.com/civitai/civitai.git
synced 2026-09-20 22:08:18 +08:00
3448438d92
The read-time metric-privacy gate (#3266) is measured at ~+35% server CPU and ~+71% event-loop longtask on api-primary when the `model-metric-privacy-readtime` flag is ON. #3322 cached membership validity but delivered ~zero benefit — because on the hot (nothing-hidden) path the membership lookup is never even called (membershipCandidates is empty), so caching it optimizes a branch the hot path skips. The real always-run cost is elsewhere: the feed / v1-list / associated read paths each ran an unconditional per-request `dbRead.user.findMany({ select: { settings } })` over EVERY owner in the response, fetching and synchronously deserializing each owner's full (large, accumulating) `settings` JSON blob just to read three booleans (hideModelBuzz/Downloads/Generations). That per-request, per-owner large-blob deserialize is the synchronous longtask, and it's exactly what #3322 left in place (it must read settings to evaluate its own "skip when nothing hidden" short-circuit). These paths also bypassed the existing batched Redis userSettingsCache entirely. Fix: add `getUserMetricPrivacyDefaultsMap(userIds)` — a read-through packed Redis cache of the tiny derived 3-boolean triple per user, mirroring the proven `getValidCreatorMembershipMap` pattern in the same dependency-light module. DB-query the misses only; fail open to the uncached DB path on any Redis error; bust on `setUserSetting` (TTL backstops other writers). The three hot paths now read the tiny triple instead of full settings, so the large-blob deserialize leaves the event loop. Byte-identical privacy: the resolvers still AND the stored hide flags with live membership; a default is `!!settings.hideModelX` before and after. Worst-case staleness is a <=10-min-late reflection of a user toggling their OWN default — the same class as userSettingsCache/membership — and can never expose another creator's metric that membership would hide. RCA + verification plan: claudedocs/rca-readtime-metric-privacy-cpu-2026-07-24.md Verify: re-run the same flag A/B (ON->OFF->ON) on api-primary; the ON CPU + longtask should collapse toward the OFF baseline. Tests: derived-cache hit/miss/batch-fill/fail-open/bust + byte-identical-vs-raw-settings + never-over-hides (unset flag -> false). tsc --noEmit clean. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>