a9ce071a51
FileContentCache (moka, 512 MiB) was keyed by the file UUID, so content that the CDC store already deduplicates to ONE blob on disk was cached once PER FILE in RAM: N files sharing a blob held N copies, all counting against the 512 MiB cap. With effective dedup the cache filled with duplicates and thrashed. Key it by the blob hash instead (already on FileDto::content_hash): - The in-RAM cache now benefits from dedup like the disk does — each distinct blob is cached once and shared across every file/user that references it, so a download by user A warms the cache for user B's identical content. - Content is immutable by hash, so entries never go stale; the existing invalidate(file_id) calls become harmless no-ops (a UUID never matches a hash key) and can be removed in a later cleanup. - ETag is now the immutable content hash (strong validator). - Guarded: a hash-less stub DTO disables caching for that request rather than colliding every such file on the empty key. Response Content-Type still comes from the DTO, not the cache, so keying does not affect the served MIME (verified). Benchmark (real moka, exact 512 MiB/weight config, 400 files x 4 MiB = 1600 MiB working set, 4000 uniform-random accesses): dedup 1x : file_id 35.8% hit / 2568 reads vs hash 35.6% / 2577 (no dedup -> no change; control) dedup 5x : file_id 35.8% hit / 2570 reads vs hash 98.0% / 80 (32x fewer disk reads, RAM 512->320 MiB) dedup 20x: file_id 35.1% hit / 2596 reads vs hash 99.5% / 20 (130x fewer disk reads, RAM 512->80 MiB) The win scales with the dedup ratio; with no dedup it is a no-op. https://claude.ai/code/session_01DCszkkU11LYxMEUWr4setK