Files
2025-10-30 16:32:04 +11:00

435 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
1. **Artist Information Cache** (JSON)
2. **Artist Image Cache** (Local files)
3. **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
```json
{
"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 cache
- `save_artist_info_to_cache()` - Write to cache
- `get_cache_path()` - Generate safe filename
### API Endpoints
**Get Artist Info (with cache):**
```http
GET /api/artists/{artist_name}/info
```
**Clear Single Artist Cache:**
```http
DELETE /api/artists/{artist_name}/cache
```
Returns: `{"message": "Cache cleared for Artist Name"}`
**Clear All Artist Cache:**
```http
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
1. **Deezer API** (primary)
- High quality: 1000×1000px
- Format: JPG
2. **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.jpg`
- `Guns N' Roses``Guns_N__Roses.jpg`
- `Beyoncé``Beyonc_.jpg`
---
## 3. Browser Cache
### Theme Preference
**Storage**: localStorage
**Key**: `theme`
**Values**: `"light"` | `"dark"`
**Duration**: Permanent (until cleared)
```typescript
localStorage.setItem('theme', 'dark')
const theme = localStorage.getItem('theme')
```
### Play Mode
**Storage**: localStorage
**Key**: `playMode`
**Values**: `"loop"` | `"shuffle"` | `"repeat-one"`
**Duration**: Permanent (until cleared)
```typescript
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
```typescript
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:**
```bash
curl -X DELETE http://localhost:8000/api/artists/Westlife/cache
```
**Backend - All Artists:**
```bash
curl -X DELETE http://localhost:8000/api/artists/cache/all
```
**Browser - Clear All:**
```javascript
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`
```python
CACHE_DURATION_DAYS = 30 # Adjust as needed
```
### Cache Directories
**File**: `backend/app/core/config.py`
```python
MUSIC_DIR = os.path.join(BASE_DIR, "data", "music")
# Cache created automatically in data/cache/
```
---
## Monitoring Cache
### Check Cache Size
```bash
# 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
```bash
# Count cached artists
ls -1 data/cache/artists/ | wc -l
# List all cached artists
ls -1 data/cache/artists/
```
### Check Cache Age
```bash
# 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:**
1. Image file exists: `ls data/cache/artist_images/`
2. Static files mounted: Check `main.py` - `/cache` route
3. Network tab: Check actual URL being requested
4. Cache JSON: Check if `image` field has correct path
**Solution:**
```bash
# Clear and refresh cache
rm data/cache/artists/{artist_name}.json
rm data/cache/artist_images/{artist_name}.jpg
```
### Issue: Cache not clearing
**Check:**
1. File permissions: `ls -la data/cache/`
2. API endpoint: `curl -X DELETE .../cache`
**Solution:**
```bash
# Manual clear
rm -rf data/cache/artists/*
rm -rf data/cache/artist_images/*
```
### Issue: Old data being served
**Cause:** Cache not expired yet
**Solution:**
```bash
# 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
1. **Cache Warming** - Pre-fetch popular artists
2. **Smart Expiration** - Expire based on artist popularity
3. **Cache Analytics** - Track hit/miss ratios
4. **CDN Integration** - Upload images to CDN
5. **Progressive Images** - Blur-up loading
### Potential Optimizations
1. **WebP Conversion** - Smaller file sizes
2. **Image Resizing** - Multiple sizes for different views
3. **Lazy Loading** - Only load visible images
4. **Service Worker** - Offline-first approach
---
## Related Files
### Backend
- `backend/app/api/artist.py` - Cache implementation
- `backend/main.py` - Static file serving
- `backend/app/core/config.py` - Configuration
### Frontend
- `frontend/src/components/artist/ArtistsPage.tsx` - Display avatars
- `frontend/src/components/artist/ArtistDetailPage.tsx` - Hero images
- `frontend/src/App.tsx` - Theme/mode caching
---
## Summary
YouMusic uses a three-tier caching system:
1. **API Data Cache** (30 days) - Artist metadata
2. **Image File Cache** (30 days) - Artist avatars
3. **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