8.8 KiB
Caching Documentation
This document describes all caching mechanisms in YouMusic to improve performance and reduce external API calls.
Overview
YouMusic implements a multi-layered caching strategy:
- Artist Information Cache (JSON)
- Artist Image Cache (Local files)
- Browser Cache (localStorage & HTTP caching)
1. Artist Information Cache
Location
data/cache/artists/{artist_name}.json
Purpose
Cache artist metadata from Deezer and MusicBrainz APIs to avoid repeated API calls.
Duration
30 days (configurable via CACHE_DURATION_DAYS)
Data Cached
{
"name": "Artist Name",
"image": "cache/artist_images/Artist_Name.jpg",
"bio": "Type: Group • Country: US",
"listeners": 1234567,
"playcount": null
}
Cache Flow
1. User visits artist page
2. Check if {artist_name}.json exists
3. If exists & < 30 days old → Return cached data
4. If expired or missing → Fetch from API
5. Save to cache file
6. Return fresh data
Implementation
- File:
backend/app/api/artist.py - Functions:
get_cached_artist_info()- Read from cachesave_artist_info_to_cache()- Write to cacheget_cache_path()- Generate safe filename
API Endpoints
Get Artist Info (with cache):
GET /api/artists/{artist_name}/info
Clear Single Artist Cache:
DELETE /api/artists/{artist_name}/cache
Returns: {"message": "Cache cleared for Artist Name"}
Clear All Artist Cache:
DELETE /api/artists/cache/all
Returns: {"message": "Cleared 15 cached artists"}
2. Artist Image Cache
Location
data/cache/artist_images/{artist_name}.jpg
Purpose
Download and store artist images locally to:
- Reduce bandwidth
- Faster loading
- Offline support
- Avoid external CDN dependencies
Duration
30 days (same as artist info)
Image Sources
- Deezer API (primary)
- High quality: 1000×1000px
- Format: JPG
- External URLs (for streaming songs)
- From YouTube/Bilibili thumbnails
Cache Flow
1. Fetch artist info from API
2. If image URL exists:
a. Download image file
b. Save to data/cache/artist_images/
c. Update artist info with local path
3. Serve from /cache/artist_images/ endpoint
Implementation
- File:
backend/app/api/artist.py - Function:
download_and_cache_artist_image() - Served via: FastAPI StaticFiles at
/cache
Supported Formats
.jpg(primary).png.webp
File Naming
Artist names are sanitized for safe filenames:
AC/DC→AC_DC.jpgGuns N' Roses→Guns_N__Roses.jpgBeyoncé→Beyonc_.jpg
3. Browser Cache
Theme Preference
Storage: localStorage
Key: theme
Values: "light" | "dark"
Duration: Permanent (until cleared)
localStorage.setItem('theme', 'dark')
const theme = localStorage.getItem('theme')
Play Mode
Storage: localStorage
Key: playMode
Values: "loop" | "shuffle" | "repeat-one"
Duration: Permanent (until cleared)
localStorage.setItem('playMode', 'shuffle')
const mode = localStorage.getItem('playMode')
TanStack Query Cache
Location: In-memory (React) Duration: 5 minutes (default) Caches:
- Artist list
- Playlist data
- Music library
- Download status
queryClient.setQueryData(['artists'], cachedData)
Cache Directory Structure
data/
├── cache/
│ ├── artists/ # Artist metadata JSON files
│ │ ├── Westlife.json
│ │ ├── Taylor_Swift.json
│ │ ├── Ed_Sheeran.json
│ │ └── ...
│ │
│ └── artist_images/ # Artist avatar images
│ ├── Westlife.jpg
│ ├── Taylor_Swift.jpg
│ ├── Ed_Sheeran.jpg
│ └── ...
│
├── music/ # Music files & thumbnails
│ ├── song1.mp3
│ ├── song2.mp3
│ └── thumbnails/
│ ├── song1.jpg
│ └── song2.jpg
│
└── uploads/ # User uploaded files
Cache Management
Automatic Expiration
- When: File modification time > 30 days
- Action: File deleted on next request
- Trigger: Automatic on read
Manual Clearing
Backend - Single Artist:
curl -X DELETE http://localhost:8000/api/artists/Westlife/cache
Backend - All Artists:
curl -X DELETE http://localhost:8000/api/artists/cache/all
Browser - Clear All:
localStorage.clear()
queryClient.clear()
Performance Impact
Without Cache (First Request)
1. Deezer API call: ~300ms
2. Image download: ~500ms
3. File save: ~50ms
Total: ~850ms
With Cache (Subsequent Requests)
1. Read JSON file: ~2ms
2. Serve cached image: ~5ms
Total: ~7ms
Speed Improvement: ~120x faster! 🚀
Cache Statistics
Storage Usage (Example)
Artist Info Cache:
- 100 artists × 2KB = 200KB
Artist Images:
- 100 artists × 150KB = 15MB
Total Cache Size: ~15.2MB
API Call Reduction
Without cache:
- 100 artists × 2 API calls = 200 calls
With cache (30 days):
- 100 artists × 2 calls / 30 days = ~7 calls/day
Reduction: 97% fewer API calls! 📉
Configuration
Cache Duration
File: backend/app/api/artist.py
CACHE_DURATION_DAYS = 30 # Adjust as needed
Cache Directories
File: backend/app/core/config.py
MUSIC_DIR = os.path.join(BASE_DIR, "data", "music")
# Cache created automatically in data/cache/
Monitoring Cache
Check Cache Size
# Artist info cache
du -sh data/cache/artists/
# Artist images cache
du -sh data/cache/artist_images/
# Total cache
du -sh data/cache/
List Cached Artists
# Count cached artists
ls -1 data/cache/artists/ | wc -l
# List all cached artists
ls -1 data/cache/artists/
Check Cache Age
# Find old cache files (>30 days)
find data/cache/artists/ -type f -mtime +30
# Delete old cache files
find data/cache/artists/ -type f -mtime +30 -delete
Troubleshooting
Issue: Artist image not showing
Check:
- Image file exists:
ls data/cache/artist_images/ - Static files mounted: Check
main.py-/cacheroute - Network tab: Check actual URL being requested
- Cache JSON: Check if
imagefield has correct path
Solution:
# Clear and refresh cache
rm data/cache/artists/{artist_name}.json
rm data/cache/artist_images/{artist_name}.jpg
Issue: Cache not clearing
Check:
- File permissions:
ls -la data/cache/ - API endpoint:
curl -X DELETE .../cache
Solution:
# Manual clear
rm -rf data/cache/artists/*
rm -rf data/cache/artist_images/*
Issue: Old data being served
Cause: Cache not expired yet
Solution:
# Force refresh by deleting cache
curl -X DELETE http://localhost:8000/api/artists/{name}/cache
# Or delete manually
rm data/cache/artists/{artist_name}.json
Best Practices
✅ Do's
- Let cache expire naturally (30 days)
- Use cache clearing endpoints for manual refresh
- Monitor cache size periodically
- Keep cache duration reasonable (7-90 days)
❌ Don'ts
- Don't manually edit cache JSON files
- Don't commit cache to git (add to .gitignore)
- Don't set cache duration too short (<1 day)
- Don't disable caching (performance impact)
Future Improvements
Planned Features
- Cache Warming - Pre-fetch popular artists
- Smart Expiration - Expire based on artist popularity
- Cache Analytics - Track hit/miss ratios
- CDN Integration - Upload images to CDN
- Progressive Images - Blur-up loading
Potential Optimizations
- WebP Conversion - Smaller file sizes
- Image Resizing - Multiple sizes for different views
- Lazy Loading - Only load visible images
- Service Worker - Offline-first approach
Related Files
Backend
backend/app/api/artist.py- Cache implementationbackend/main.py- Static file servingbackend/app/core/config.py- Configuration
Frontend
frontend/src/components/artist/ArtistsPage.tsx- Display avatarsfrontend/src/components/artist/ArtistDetailPage.tsx- Hero imagesfrontend/src/App.tsx- Theme/mode caching
Summary
YouMusic uses a three-tier caching system:
- API Data Cache (30 days) - Artist metadata
- Image File Cache (30 days) - Artist avatars
- Browser Cache (permanent) - User preferences
This reduces:
- API calls by 97%
- Page load time by 120x
- Bandwidth usage by ~15MB per 100 artists
All caches auto-expire and can be manually cleared via API endpoints.
Last Updated: 2024-10-30 Version: 1.0.0