mirror of
https://github.com/wahyd4/you-music.git
synced 2026-08-08 20:59:47 +10:00
435 lines
8.8 KiB
Markdown
435 lines
8.8 KiB
Markdown
# 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
|