fix(images): cache blob avatars by durable blob id, not the ephemeral URL - #1155
Merged
Conversation
… URL Blob download URLs are re-minted and expire on every fetch, while the bytes they address are immutable. The avatar loader keyed Coil's memory/disk caches on that rotating URL, so every new response produced a fresh cache key and a guaranteed miss — the BlurHash placeholder flashed and the same bytes were re-downloaded on every load and cold start. Key the caches on the durable blob id instead: - MediaItem gains cacheKeyForSize/cacheKeyBelow, derived from the rendition's blobId (base58) rather than the download URL. - ProfileAvatar sets both memoryCacheKey and diskCacheKey to that stable key (data() still carries the current URL for the actual fetch), and keys the placeholderMemoryCacheKey upgrade the same way. - Add ImmutableBlobCacheStrategy so Coil serves cached blobs unconditionally and never revalidates/re-downloads against the expiring URL's cache headers. Result: a loaded avatar is served from cache on re-display and across launches with no BlurHash flash. Blobs are static, so no eviction logic is needed beyond the existing 50 MB disk cap.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Blob avatars that were already loaded get re-downloaded — you see the BlurHash placeholder, then the image, every time — even for images the app has fetched before.
Root cause: a blob's
download_urlis ephemeral. The proto (blob/v1/model.proto) documents it as "Ephemeral, server-minted URL… Re-issued on every fetch" with an expiry, while the bytes it addresses are immutable.ProfileAvatarkeyed Coil's memory and disk caches on that rotating URL (.memoryCacheKey(photoUri)/.data(url)), so every new gRPC response minted a new URL → a new cache key → a guaranteed miss → BlurHash flash + re-download, both within a session and across cold starts.Fix
Key the caches on the durable blob id instead of the URL, and treat cached blobs as immutable.
MediaItemgainscacheKeyForSize()/cacheKeyBelow(), derived from the rendition'sblobId(base58) — a stable identity that survives URL rotation and app restarts.ProfileAvatarsets bothmemoryCacheKeyanddiskCacheKeyto that stable key..data()still carries the current URL so the actual network fetch works; only the cache identity changes. TheplaceholderMemoryCacheKeyupgrade (smaller rendition → larger) is keyed the same way so it keeps working across surfaces.ImmutableBlobCacheStrategy(new) is wired into theImageLoader. Coil's default strategy is a stock HTTP cache that would revalidate/re-fetch based on the expiring URL's headers; since blobs are static, this serves a cached response unconditionally and always persists on write.Result
Blobs are static, so no eviction logic is needed beyond the existing 50 MB disk LRU cap.
Notes / scope
MessageBubble) is still aTODOand not rendered; when it lands it should reuseMediaItem.cacheKeyForSize()the same way.Testing
:services:flipcash,:apps:flipcash:shared:common-ui,:apps:flipcash:appcompile clean.