Overview
ThumbnailCache provides a two-tier caching system for R2 object thumbnails. It combines in-memory caching with disk persistence and implements request coalescing to prevent duplicate fetches. The actor-based design ensures thread-safe access from any context.
Located at:
Fiaxe/Services/ThumbnailCache.swift:6Type Definition
Singleton Instance
Methods
thumbnail()
Retrieves or generates a thumbnail for an R2 object key.String
required
The R2 object key to generate a thumbnail for (e.g.,
"photos/image.jpg").R2Credentials
required
R2 credentials used to generate presigned URLs for fetching the image.
nil if generation fails.
Implementation Details
- Memory cache - Instant return if cached in
NSCache - Disk cache - Load from disk if available, promote to memory
- Network fetch - Generate thumbnail from R2, cache in both memory and disk
clearMemory()
Clears the entire in-memory cache.Cache Configuration
The cache is configured with size limits:Int
Maximum number of images in memory cache (500).
Int
Maximum memory footprint in bytes (100 MB).
NSCache automatically evicts least-recently-used items when limits are exceeded.
Disk Cache
Thumbnails are persisted to the user’s cache directory:File Naming
Cache keys are sanitized for safe filenames:photos/vacation.jpg→photos_vacation.jpg.pngbucket:folder/file.png→bucket_folder_file.png.png
Storage Format
All thumbnails are stored as PNG:Thumbnail Generation
Image Thumbnails
Generated by downloading and resizing:Video Thumbnails
Generated using AVFoundation:Supported Images
JPEG, PNG, GIF, HEIC, BMP, TIFF, WebP
Supported Videos
MP4, MOV, AVI, MKV, WebM, M4V
Resize Algorithm
The cache maintains aspect ratio while fitting within 120×120:- 1920×1080 → 120×67.5 (fits width)
- 800×1200 → 80×120 (fits height)
- 100×100 → 100×100 (no upscaling)
Request Coalescing
Prevents duplicate fetches for the same thumbnail:- Only 1 network request is made
- All 10 requests await the same task
- All receive the same result
Bucket Scoping
Cache keys are scoped by bucket name:- Different buckets with same key names don’t share thumbnails
- Switching between buckets doesn’t show wrong thumbnails
- Cache hits are always bucket-specific
Usage Example
Performance Characteristics
Memory Efficiency
Memory Efficiency
NSCache automatically evicts items under memory pressure. The 100 MB limit prevents excessive memory usage.Disk Efficiency
Disk Efficiency
PNG compression reduces disk space. A 120×120 thumbnail typically uses 10-50 KB.
Concurrency
Concurrency
Actor isolation ensures safe concurrent access. Multiple views can request thumbnails simultaneously without race conditions.
Network Efficiency
Network Efficiency
Request coalescing prevents duplicate downloads. Once cached, thumbnails load instantly.
Cache Persistence
Disk Cache LifetimeThe disk cache persists across app launches and remains until:
- User manually clears cache (if implemented)
- macOS automatically clears ~/Library/Caches during cleanup
- App is uninstalled
Error Handling
The cache gracefully handles errors:- Invalid presigned URL
- Network errors
- Unsupported file formats
- Corrupted images
- Disk write failures
nil rather than throwing errors, allowing UI to show fallback icons.
Thread Safety
Related Services
- AWSV4Signer - Generates presigned URLs for fetching
- QuickLookCoordinator - Full-size previews
- R2BrowseService - Provides R2Object data