Files
civitai__civitai/claudedocs
Zachary Lowden 3448438d92 perf(creator-controls): cache read-time metric-privacy DEFAULT flags (kill the settings-blob longtask) (#3331)
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>
2026-07-24 11:25:47 -05:00
..