feat: add caching debug logs and configurable max concurrent requests for Komga API to enhance performance monitoring
This commit is contained in:
317
docs/cache-debug.md
Normal file
317
docs/cache-debug.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# Debug du Cache
|
||||
|
||||
Guide pour debugger le système de caching de StripStream.
|
||||
|
||||
## Activation des logs de cache
|
||||
|
||||
### Variable d'environnement
|
||||
|
||||
Activez les logs détaillés du cache serveur avec :
|
||||
|
||||
```bash
|
||||
CACHE_DEBUG=true
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
#### Développement (docker-compose.dev.yml)
|
||||
```yaml
|
||||
environment:
|
||||
- CACHE_DEBUG=true
|
||||
```
|
||||
|
||||
#### Production (.env)
|
||||
```env
|
||||
CACHE_DEBUG=true
|
||||
```
|
||||
|
||||
## Format des logs
|
||||
|
||||
Les logs de cache apparaissent dans la console serveur avec le format suivant :
|
||||
|
||||
### Cache HIT (donnée valide)
|
||||
```
|
||||
[CACHE HIT] home-ongoing | HOME | 0.45ms
|
||||
```
|
||||
- ✅ Donnée trouvée en cache
|
||||
- ✅ Donnée encore valide (pas expirée)
|
||||
- ⚡ Retour immédiat (très rapide)
|
||||
|
||||
### Cache STALE (donnée expirée)
|
||||
```
|
||||
[CACHE STALE] home-ongoing | HOME | 0.52ms
|
||||
```
|
||||
- ✅ Donnée trouvée en cache
|
||||
- ⚠️ Donnée expirée mais toujours retournée
|
||||
- 🔄 Revalidation lancée en background
|
||||
|
||||
### Cache MISS (pas de donnée)
|
||||
```
|
||||
[CACHE MISS] home-ongoing | HOME
|
||||
```
|
||||
- ❌ Aucune donnée en cache
|
||||
- 🌐 Fetch normal depuis Komga
|
||||
- 💾 Mise en cache automatique
|
||||
|
||||
### Cache SET (mise en cache)
|
||||
```
|
||||
[CACHE SET] home-ongoing | HOME | 324.18ms
|
||||
```
|
||||
- 💾 Donnée mise en cache après fetch
|
||||
- 📊 Temps total incluant le fetch Komga
|
||||
- ✅ Prochaines requêtes seront rapides
|
||||
|
||||
### Cache REVALIDATE (revalidation background)
|
||||
```
|
||||
[CACHE REVALIDATE] home-ongoing | HOME | 287.45ms
|
||||
```
|
||||
- 🔄 Revalidation en background (après STALE)
|
||||
- 🌐 Nouvelle donnée fetched depuis Komga
|
||||
- 💾 Cache mis à jour pour les prochaines requêtes
|
||||
|
||||
### Erreur de revalidation
|
||||
```
|
||||
[CACHE REVALIDATE ERROR] home-ongoing: Error: ...
|
||||
```
|
||||
- ❌ Échec de la revalidation background
|
||||
- ⚠️ Cache ancien conservé
|
||||
- 🔄 Retry au prochain STALE
|
||||
|
||||
## Types de cache
|
||||
|
||||
Les logs affichent le type de TTL utilisé :
|
||||
|
||||
| Type | TTL | Usage |
|
||||
|------|-----|-------|
|
||||
| `DEFAULT` | 5 min | Données génériques |
|
||||
| `HOME` | 10 min | Page d'accueil |
|
||||
| `LIBRARIES` | 24h | Bibliothèques |
|
||||
| `SERIES` | 5 min | Séries |
|
||||
| `BOOKS` | 5 min | Livres |
|
||||
| `IMAGES` | 7 jours | Images |
|
||||
|
||||
## Exemple de session complète
|
||||
|
||||
```bash
|
||||
# Première requête (cache vide)
|
||||
[CACHE MISS] home-ongoing | HOME
|
||||
[CACHE SET] home-ongoing | HOME | 324.18ms
|
||||
|
||||
# Requête suivante (cache valide)
|
||||
[CACHE HIT] home-ongoing | HOME | 0.45ms
|
||||
|
||||
# 10 minutes plus tard (cache expiré)
|
||||
[CACHE STALE] home-ongoing | HOME | 0.52ms
|
||||
[CACHE REVALIDATE] home-ongoing | HOME | 287.45ms
|
||||
|
||||
# Requête suivante (cache frais)
|
||||
[CACHE HIT] home-ongoing | HOME | 0.43ms
|
||||
```
|
||||
|
||||
## Outils complémentaires
|
||||
|
||||
### 1. DevTools du navigateur
|
||||
|
||||
#### Network Tab
|
||||
- Temps de réponse < 50ms = probablement du cache serveur
|
||||
- Headers `X-Cache` si configurés
|
||||
- Onglet "Timing" pour détails
|
||||
|
||||
#### Application → Cache Storage
|
||||
Inspectez le cache du Service Worker :
|
||||
- `stripstream-cache-v1` : Ressources statiques
|
||||
- `stripstream-images-v1` : Images (covers + pages)
|
||||
|
||||
Actions disponibles :
|
||||
- ✅ Voir le contenu de chaque cache
|
||||
- 🔍 Chercher une URL spécifique
|
||||
- 🗑️ Supprimer des entrées
|
||||
- 🧹 Vider complètement un cache
|
||||
|
||||
#### Application → Service Workers
|
||||
- État du Service Worker
|
||||
- "Unregister" pour le désactiver
|
||||
- "Update" pour forcer une mise à jour
|
||||
- Console pour voir les logs SW
|
||||
|
||||
### 2. API de monitoring
|
||||
|
||||
#### Taille du cache
|
||||
```bash
|
||||
curl http://localhost:3000/api/komga/cache/size
|
||||
```
|
||||
Response :
|
||||
```json
|
||||
{
|
||||
"sizeInBytes": 15728640,
|
||||
"itemCount": 234
|
||||
}
|
||||
```
|
||||
|
||||
#### Mode actuel
|
||||
```bash
|
||||
curl http://localhost:3000/api/komga/cache/mode
|
||||
```
|
||||
Response :
|
||||
```json
|
||||
{
|
||||
"mode": "memory"
|
||||
}
|
||||
```
|
||||
|
||||
#### Vider le cache
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/komga/cache/clear
|
||||
```
|
||||
|
||||
#### Changer de mode
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/komga/cache/mode \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"mode": "file"}'
|
||||
```
|
||||
|
||||
### 3. Mode fichier : Inspection du disque
|
||||
|
||||
Si vous utilisez le mode `file`, le cache est stocké sur disque :
|
||||
|
||||
```bash
|
||||
# Voir la structure du cache
|
||||
ls -la .cache/
|
||||
|
||||
# Voir la taille totale
|
||||
du -sh .cache/
|
||||
|
||||
# Compter les fichiers
|
||||
find .cache/ -type f | wc -l
|
||||
|
||||
# Voir le contenu d'une entrée
|
||||
cat .cache/user-id/home-ongoing.json | jq
|
||||
```
|
||||
|
||||
Exemple de contenu :
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"ongoing": [...],
|
||||
"recentlyRead": [...],
|
||||
"onDeck": [...]
|
||||
},
|
||||
"expiry": 1704067200000
|
||||
}
|
||||
```
|
||||
|
||||
## Patterns de debug courants
|
||||
|
||||
### Identifier un problème de cache
|
||||
|
||||
**Symptôme** : Les données ne se rafraîchissent pas
|
||||
```bash
|
||||
# 1. Vérifier si STALE + REVALIDATE se produisent
|
||||
CACHE_DEBUG=true
|
||||
|
||||
# 2. Observer les logs
|
||||
[CACHE STALE] series-123 | SERIES | 0.5ms
|
||||
[CACHE REVALIDATE ERROR] series-123: Network error
|
||||
|
||||
# 3. Problème identifié : Komga inaccessible
|
||||
```
|
||||
|
||||
**Solution** : Vérifier la connectivité avec Komga
|
||||
|
||||
### Optimiser les performances
|
||||
|
||||
**Objectif** : Identifier les requêtes lentes
|
||||
```bash
|
||||
# Activer les logs
|
||||
CACHE_DEBUG=true
|
||||
|
||||
# Observer les temps
|
||||
[CACHE MISS] library-456-all-series | SERIES
|
||||
[CACHE SET] library-456-all-series | SERIES | 2847.32ms # ⚠️ Très lent !
|
||||
```
|
||||
|
||||
**Solution** :
|
||||
- Vérifier la taille des bibliothèques
|
||||
- Augmenter le TTL pour ces données
|
||||
- Considérer la pagination
|
||||
|
||||
### Vérifier le mode de cache
|
||||
|
||||
```bash
|
||||
# Logs après redémarrage
|
||||
[CACHE MISS] home-ongoing | HOME # Mode memory : normal
|
||||
[CACHE HIT] home-ongoing | HOME # Mode file : cache persisté
|
||||
```
|
||||
|
||||
En mode `memory` : tous les caches sont vides au démarrage
|
||||
En mode `file` : les caches survivent au redémarrage
|
||||
|
||||
## Performance attendue
|
||||
|
||||
### Temps de réponse normaux
|
||||
|
||||
| Scénario | Temps attendu | Log |
|
||||
|----------|---------------|-----|
|
||||
| Cache HIT | < 1ms | `[CACHE HIT] ... \| 0.45ms` |
|
||||
| Cache STALE | < 1ms | `[CACHE STALE] ... \| 0.52ms` |
|
||||
| Cache MISS (petit) | 50-200ms | `[CACHE SET] ... \| 124.18ms` |
|
||||
| Cache MISS (gros) | 200-1000ms | `[CACHE SET] ... \| 847.32ms` |
|
||||
| Revalidate (background) | Variable | `[CACHE REVALIDATE] ... \| 287.45ms` |
|
||||
|
||||
### Signaux d'alerte
|
||||
|
||||
⚠️ **Cache HIT > 10ms**
|
||||
- Problème : Disque lent (mode file)
|
||||
- Solution : Vérifier les I/O, passer en mode memory
|
||||
|
||||
⚠️ **Cache MISS > 2000ms**
|
||||
- Problème : Komga très lent ou données énormes
|
||||
- Solution : Vérifier Komga, optimiser la requête
|
||||
|
||||
⚠️ **REVALIDATE ERROR fréquents**
|
||||
- Problème : Komga instable ou réseau
|
||||
- Solution : Augmenter les timeouts, vérifier la connectivité
|
||||
|
||||
⚠️ **Trop de MISS successifs**
|
||||
- Problème : Cache pas conservé ou TTL trop court
|
||||
- Solution : Vérifier le mode, augmenter les TTL
|
||||
|
||||
## Désactiver les logs
|
||||
|
||||
Pour désactiver les logs de cache en production :
|
||||
|
||||
```bash
|
||||
# .env
|
||||
CACHE_DEBUG=false
|
||||
|
||||
# ou simplement commenter/supprimer la ligne
|
||||
# CACHE_DEBUG=true
|
||||
```
|
||||
|
||||
Les logs sont **automatiquement désactivés** si la variable n'est pas définie.
|
||||
|
||||
## Logs et performance
|
||||
|
||||
**Impact sur les performances** :
|
||||
- Overhead : < 0.1ms par opération
|
||||
- Pas d'écriture disque (juste console)
|
||||
- Pas d'accumulation en mémoire
|
||||
- Safe pour la production
|
||||
|
||||
**Recommandations** :
|
||||
- ✅ Activé en développement
|
||||
- ✅ Activé temporairement en production pour diagnostics
|
||||
- ❌ Pas nécessaire en production normale
|
||||
|
||||
## Conclusion
|
||||
|
||||
Le système de logs de cache est conçu pour être :
|
||||
- 🎯 **Simple** : Format clair et concis
|
||||
- ⚡ **Rapide** : Impact négligeable sur les performances
|
||||
- 🔧 **Utile** : Informations essentielles pour le debug
|
||||
- 🔒 **Optionnel** : Désactivé par défaut
|
||||
|
||||
Pour la plupart des besoins de debug, les DevTools du navigateur suffisent.
|
||||
Les logs serveur sont utiles pour comprendre le comportement du cache côté backend.
|
||||
|
||||
502
docs/caching.md
Normal file
502
docs/caching.md
Normal file
@@ -0,0 +1,502 @@
|
||||
# Système de Caching
|
||||
|
||||
Ce document décrit l'architecture et les stratégies de caching de StripStream.
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
Le système de caching est organisé en **3 couches indépendantes** avec des responsabilités clairement définies :
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ NAVIGATEUR │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ Service Worker (Cache API) │ │
|
||||
│ │ → Offline support │ │
|
||||
│ │ → Images (covers + pages) │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ SERVEUR NEXT.JS │
|
||||
│ ┌────────────────────────────────────────────────────────┐ │
|
||||
│ │ ServerCacheService │ │
|
||||
│ │ → Données API Komga │ │
|
||||
│ │ → Stale-while-revalidate │ │
|
||||
│ │ → Mode fichier ou mémoire │ │
|
||||
│ └────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ SERVEUR KOMGA │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Couche 1 : Service Worker (Client)
|
||||
|
||||
### Fichier
|
||||
`public/sw.js`
|
||||
|
||||
### Responsabilité
|
||||
- Support offline de l'application
|
||||
- Cache persistant des images (couvertures et pages de livres)
|
||||
- Cache des ressources statiques Next.js
|
||||
|
||||
### Stratégies
|
||||
|
||||
#### Images : Cache-First
|
||||
```javascript
|
||||
// Pour toutes les images (covers + pages)
|
||||
const isImageResource = (url) => {
|
||||
return (
|
||||
(url.includes("/api/v1/books/") &&
|
||||
(url.includes("/pages") || url.includes("/thumbnail") || url.includes("/cover"))) ||
|
||||
(url.includes("/api/komga/images/") &&
|
||||
(url.includes("/series/") || url.includes("/books/")) &&
|
||||
url.includes("/thumbnail"))
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
**Comportement** :
|
||||
1. Vérifier si l'image est dans le cache
|
||||
2. Si oui → retourner depuis le cache
|
||||
3. Si non → fetch depuis le réseau
|
||||
4. Si succès → mettre en cache + retourner
|
||||
5. Si échec → retourner 404
|
||||
|
||||
**Avantages** :
|
||||
- Performance maximale (lecture instantanée depuis le cache)
|
||||
- Fonctionne offline une fois les images chargées
|
||||
- Économise la bande passante
|
||||
|
||||
#### Navigation et ressources statiques : Network-First
|
||||
```javascript
|
||||
// Pour les pages et ressources _next/static
|
||||
event.respondWith(
|
||||
fetch(request)
|
||||
.then((response) => {
|
||||
// Mise en cache si succès
|
||||
if (response.ok && (isNextStaticResource || isNavigation)) {
|
||||
cache.put(request, response.clone());
|
||||
}
|
||||
return response;
|
||||
})
|
||||
.catch(async () => {
|
||||
// Fallback sur le cache si offline
|
||||
const cachedResponse = await cache.match(request);
|
||||
if (cachedResponse) return cachedResponse;
|
||||
|
||||
// Page offline si navigation
|
||||
if (request.mode === "navigate") {
|
||||
return cache.match("/offline.html");
|
||||
}
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
**Avantages** :
|
||||
- Toujours la dernière version quand online
|
||||
- Fallback offline si nécessaire
|
||||
- Navigation fluide même sans connexion
|
||||
|
||||
### Caches
|
||||
|
||||
| Cache | Usage | Stratégie | Taille |
|
||||
|-------|-------|-----------|--------|
|
||||
| `stripstream-cache-v1` | Ressources statiques + pages | Network-First | ~5 MB |
|
||||
| `stripstream-images-v1` | Images (covers + pages) | Cache-First | Illimité |
|
||||
|
||||
### Nettoyage
|
||||
- Automatique lors de l'activation du Service Worker
|
||||
- Suppression des anciennes versions de cache
|
||||
- Pas d'expiration (contrôlé par l'utilisateur via les paramètres du navigateur)
|
||||
|
||||
## Couche 2 : ServerCacheService (Serveur)
|
||||
|
||||
### Fichier
|
||||
`src/lib/services/server-cache.service.ts`
|
||||
|
||||
### Responsabilité
|
||||
- Cache des réponses API Komga côté serveur
|
||||
- Optimisation des temps de réponse
|
||||
- Réduction de la charge sur Komga
|
||||
|
||||
### Stratégie : Stale-While-Revalidate
|
||||
|
||||
Cette stratégie est **la clé de la performance** de l'application.
|
||||
|
||||
#### Principe
|
||||
```
|
||||
Requête → Cache existe ?
|
||||
├─ Non → Fetch normal + mise en cache
|
||||
└─ Oui → Cache valide ?
|
||||
├─ Oui → Retourne immédiatement
|
||||
└─ Non → Retourne le cache expiré (stale)
|
||||
ET revalide en background
|
||||
```
|
||||
|
||||
#### Implémentation
|
||||
```typescript
|
||||
async getOrSet<T>(
|
||||
key: string,
|
||||
fetcher: () => Promise<T>,
|
||||
type: keyof typeof ServerCacheService.DEFAULT_TTL = "DEFAULT"
|
||||
): Promise<T> {
|
||||
const cacheKey = `${user.id}-${key}`;
|
||||
const cachedResult = this.getStale(cacheKey);
|
||||
|
||||
if (cachedResult !== null) {
|
||||
const { data, isStale } = cachedResult;
|
||||
|
||||
// Si le cache est expiré, revalider en background
|
||||
if (isStale) {
|
||||
this.revalidateInBackground(cacheKey, fetcher, type, key);
|
||||
}
|
||||
|
||||
return data as T; // Retour immédiat
|
||||
}
|
||||
|
||||
// Pas de cache, fetch normal
|
||||
const data = await fetcher();
|
||||
this.set(cacheKey, data, type);
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
#### Avantages
|
||||
✅ **Temps de réponse constant** : Le cache expiré est retourné instantanément
|
||||
✅ **Données fraîches** : Revalidation en background pour la prochaine requête
|
||||
✅ **Pas de délai** : L'utilisateur ne subit jamais l'attente de revalidation
|
||||
✅ **Résilience** : Même si Komga est lent, l'app reste rapide
|
||||
|
||||
#### Inconvénients
|
||||
⚠️ Les données peuvent être légèrement obsolètes (jusqu'au prochain refresh)
|
||||
⚠️ Nécessite un cache initialisé (première requête toujours lente)
|
||||
|
||||
### Modes de stockage
|
||||
|
||||
L'utilisateur peut choisir entre deux modes :
|
||||
|
||||
#### Mode Mémoire (par défaut)
|
||||
```typescript
|
||||
cacheMode: "memory"
|
||||
```
|
||||
- Cache stocké en RAM
|
||||
- **Performances** : Très rapide (lecture < 1ms)
|
||||
- **Persistance** : Perdu au redémarrage du serveur
|
||||
- **Capacité** : Limitée par la RAM disponible
|
||||
- **Idéal pour** : Développement, faible charge
|
||||
|
||||
#### Mode Fichier
|
||||
```typescript
|
||||
cacheMode: "file"
|
||||
```
|
||||
- Cache stocké sur disque (`.cache/`)
|
||||
- **Performances** : Rapide (lecture 5-10ms)
|
||||
- **Persistance** : Survit aux redémarrages
|
||||
- **Capacité** : Limitée par l'espace disque
|
||||
- **Idéal pour** : Production, haute charge
|
||||
|
||||
### Time-To-Live (TTL)
|
||||
|
||||
Chaque type de données a un TTL configuré :
|
||||
|
||||
| Type | TTL par défaut | Justification |
|
||||
|------|----------------|---------------|
|
||||
| `DEFAULT` | 5 minutes | Données génériques |
|
||||
| `HOME` | 10 minutes | Page d'accueil (données agrégées) |
|
||||
| `LIBRARIES` | 24 heures | Bibliothèques (rarement modifiées) |
|
||||
| `SERIES` | 5 minutes | Séries (métadonnées + progression) |
|
||||
| `BOOKS` | 5 minutes | Livres (métadonnées + progression) |
|
||||
| `IMAGES` | 7 jours | Images (immuables) |
|
||||
|
||||
#### Configuration personnalisée
|
||||
|
||||
Les TTL peuvent être personnalisés par l'utilisateur via la base de données :
|
||||
|
||||
```typescript
|
||||
// Modèle Prisma : TTLConfig
|
||||
{
|
||||
defaultTTL: 5 * 60 * 1000,
|
||||
homeTTL: 10 * 60 * 1000,
|
||||
librariesTTL: 24 * 60 * 60 * 1000,
|
||||
seriesTTL: 5 * 60 * 1000,
|
||||
booksTTL: 5 * 60 * 1000,
|
||||
imagesTTL: 7 * 24 * 60 * 60 * 1000,
|
||||
}
|
||||
```
|
||||
|
||||
### Isolation par utilisateur
|
||||
|
||||
Chaque utilisateur a son propre cache :
|
||||
|
||||
```typescript
|
||||
const cacheKey = `${user.id}-${key}`;
|
||||
```
|
||||
|
||||
**Avantages** :
|
||||
- Pas de collision entre utilisateurs
|
||||
- Progression de lecture individuelle
|
||||
- Préférences personnalisées
|
||||
|
||||
### Invalidation du cache
|
||||
|
||||
Le cache peut être invalidé :
|
||||
|
||||
#### Manuellement
|
||||
```typescript
|
||||
await cacheService.delete(key); // Une clé
|
||||
await cacheService.deleteAll(prefix); // Toutes les clés avec préfixe
|
||||
await cacheService.clear(); // Tout le cache
|
||||
```
|
||||
|
||||
#### Automatiquement
|
||||
- Lors d'une mise à jour de progression
|
||||
- Lors d'un changement de favoris
|
||||
- Lors de la suppression d'une série
|
||||
|
||||
#### API
|
||||
```
|
||||
DELETE /api/komga/cache/clear // Vider tout le cache
|
||||
DELETE /api/komga/home // Invalider le cache home
|
||||
```
|
||||
|
||||
## Couche 3 : Cache HTTP (Navigateur)
|
||||
|
||||
### Responsabilité
|
||||
- Cache basique géré par le navigateur
|
||||
- Headers HTTP standard
|
||||
|
||||
### Configuration
|
||||
|
||||
#### Next.js ISR (Incremental Static Regeneration)
|
||||
```typescript
|
||||
export const revalidate = 60; // Revalidation toutes les 60 secondes
|
||||
```
|
||||
|
||||
Utilisé uniquement pour les routes avec rendu statique.
|
||||
|
||||
#### Headers explicites (désactivé)
|
||||
|
||||
Les headers HTTP explicites ont été **supprimés** car :
|
||||
- Le ServerCacheService gère déjà le caching efficacement
|
||||
- Évite la confusion entre plusieurs couches de cache
|
||||
- Simplifie le debugging
|
||||
|
||||
Avant (supprimé) :
|
||||
```typescript
|
||||
NextResponse.json(data, {
|
||||
headers: {
|
||||
'Cache-Control': 'public, s-maxage=60, stale-while-revalidate=120'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Maintenant :
|
||||
```typescript
|
||||
NextResponse.json(data); // Pas de headers
|
||||
```
|
||||
|
||||
## Flow de données complet
|
||||
|
||||
Exemple : Chargement de la page d'accueil
|
||||
|
||||
```
|
||||
1. Utilisateur → GET /
|
||||
↓
|
||||
2. Next.js → HomeService.getHomeData()
|
||||
↓
|
||||
3. HomeService → ServerCacheService.getOrSet("home-ongoing", ...)
|
||||
↓
|
||||
4. ServerCacheService
|
||||
├─ Cache valide ? → Retourne immédiatement
|
||||
├─ Cache expiré ? → Retourne cache + revalide en background
|
||||
└─ Pas de cache ? → Fetch Komga + mise en cache
|
||||
↓
|
||||
5. Response → Client
|
||||
↓
|
||||
6. Images → Service Worker (Cache-First)
|
||||
├─ En cache ? → Lecture instantanée
|
||||
└─ Pas en cache ? → Fetch + mise en cache
|
||||
```
|
||||
|
||||
### Temps de réponse typiques
|
||||
|
||||
| Scénario | Temps | Détails |
|
||||
|----------|-------|---------|
|
||||
| Cache ServerCache valide + SW | ~50ms | Optimal |
|
||||
| Cache ServerCache expiré + SW | ~50ms | Revalidation en background |
|
||||
| Pas de cache ServerCache + SW | ~200-500ms | Première requête |
|
||||
| Cache SW uniquement | ~10ms | Images seulement |
|
||||
| Tout à froid | ~500-1000ms | Pire cas |
|
||||
|
||||
## Cas d'usage
|
||||
|
||||
### 1. Première visite
|
||||
```
|
||||
User → App → Komga (tous les caches vides)
|
||||
Temps : ~500-1000ms
|
||||
```
|
||||
|
||||
### 2. Visite suivante (online)
|
||||
```
|
||||
User → ServerCache (valide) → Images SW
|
||||
Temps : ~50ms
|
||||
```
|
||||
|
||||
### 3. Cache expiré (online)
|
||||
```
|
||||
User → ServerCache (stale) → Retour immédiat
|
||||
↓
|
||||
Revalidation background → Mise à jour cache
|
||||
Temps ressenti : ~50ms (aucun délai)
|
||||
```
|
||||
|
||||
### 4. Mode offline
|
||||
```
|
||||
User → Service Worker cache uniquement
|
||||
Fonctionnalités :
|
||||
✅ Navigation entre pages déjà visitées
|
||||
✅ Consultation des images déjà vues
|
||||
❌ Nouvelles données (nécessite connexion)
|
||||
```
|
||||
|
||||
## Monitoring et debug
|
||||
|
||||
### Logs de cache (recommandé pour le dev)
|
||||
|
||||
Activez les logs détaillés du cache serveur :
|
||||
|
||||
```bash
|
||||
# Dans docker-compose.dev.yml ou .env
|
||||
CACHE_DEBUG=true
|
||||
```
|
||||
|
||||
**Format des logs** :
|
||||
```
|
||||
[CACHE HIT] home-ongoing | HOME | 0.45ms # Cache valide
|
||||
[CACHE STALE] home-ongoing | HOME | 0.52ms # Cache expiré (retourné + revalidation)
|
||||
[CACHE MISS] home-ongoing | HOME # Pas de cache
|
||||
[CACHE SET] home-ongoing | HOME | 324.18ms # Mise en cache
|
||||
[CACHE REVALIDATE] home-ongoing | HOME | 287ms # Revalidation background
|
||||
```
|
||||
|
||||
📖 **Documentation complète** : [docs/cache-debug.md](./cache-debug.md)
|
||||
|
||||
### API de monitoring
|
||||
|
||||
#### Taille du cache serveur
|
||||
```bash
|
||||
GET /api/komga/cache/size
|
||||
Response: { sizeInBytes: 15728640, itemCount: 234 }
|
||||
```
|
||||
|
||||
#### Mode de cache actuel
|
||||
```bash
|
||||
GET /api/komga/cache/mode
|
||||
Response: { mode: "memory" }
|
||||
```
|
||||
|
||||
#### Changer le mode
|
||||
```bash
|
||||
POST /api/komga/cache/mode
|
||||
Body: { mode: "file" }
|
||||
```
|
||||
|
||||
#### Vider le cache
|
||||
```bash
|
||||
POST /api/komga/cache/clear
|
||||
```
|
||||
|
||||
### DevTools du navigateur
|
||||
|
||||
#### Network Tab
|
||||
- Temps de réponse < 50ms = cache serveur
|
||||
- Headers `X-Cache` si configurés
|
||||
- Onglet "Timing" pour détails
|
||||
|
||||
#### Application → Cache Storage
|
||||
Inspecter le Service Worker :
|
||||
- `stripstream-cache-v1` : Ressources statiques
|
||||
- `stripstream-images-v1` : Images
|
||||
|
||||
Actions disponibles :
|
||||
- Voir le contenu
|
||||
- Supprimer des entrées
|
||||
- Vider complètement
|
||||
|
||||
#### Application → Service Workers
|
||||
- État du Service Worker
|
||||
- "Unregister" pour le désactiver
|
||||
- "Update" pour forcer une mise à jour
|
||||
|
||||
## Optimisations futures possibles
|
||||
|
||||
### 1. Cache Redis (optionnel)
|
||||
- Pour un déploiement multi-instances
|
||||
- Cache partagé entre plusieurs serveurs
|
||||
- TTL natif Redis
|
||||
|
||||
### 2. Compression
|
||||
- Compresser les données en cache (Brotli/Gzip)
|
||||
- Économie d'espace disque/mémoire
|
||||
- Trade-off CPU vs espace
|
||||
|
||||
### 3. Prefetching intelligent
|
||||
- Précharger les séries en cours de lecture
|
||||
- Précharger les pages suivantes dans le reader
|
||||
- Basé sur l'historique utilisateur
|
||||
|
||||
### 4. Cache Analytics
|
||||
- Ratio hit/miss
|
||||
- Temps de réponse moyens
|
||||
- Identification des données les plus consultées
|
||||
|
||||
## Bonnes pratiques
|
||||
|
||||
### Pour les développeurs
|
||||
|
||||
✅ **Utiliser BaseApiService.fetchWithCache()**
|
||||
```typescript
|
||||
await this.fetchWithCache<T>(
|
||||
"cache-key",
|
||||
async () => this.fetchFromApi(...),
|
||||
"HOME" // Type de TTL
|
||||
);
|
||||
```
|
||||
|
||||
✅ **Invalider le cache après modification**
|
||||
```typescript
|
||||
await HomeService.invalidateHomeCache();
|
||||
```
|
||||
|
||||
✅ **Choisir le bon TTL**
|
||||
- Court (1-5 min) : Données qui changent souvent
|
||||
- Moyen (10-30 min) : Données agrégées
|
||||
- Long (24h+) : Données quasi-statiques
|
||||
|
||||
❌ **Ne pas cacher les mutations**
|
||||
Les POST/PUT/DELETE ne doivent jamais être cachés
|
||||
|
||||
❌ **Ne pas oublier l'isolation utilisateur**
|
||||
Toujours préfixer avec `userId` pour les données personnelles
|
||||
|
||||
### Pour les utilisateurs
|
||||
|
||||
- **Mode mémoire** : Plus rapide, mais cache perdu au redémarrage
|
||||
- **Mode fichier** : Persistant, idéal pour production
|
||||
- **Vider le cache** : En cas de problème d'affichage
|
||||
- **Offline** : Consulter les pages déjà visitées
|
||||
|
||||
## Conclusion
|
||||
|
||||
Le système de caching de StripStream est conçu pour :
|
||||
|
||||
🎯 **Performance** : Temps de réponse constants grâce au stale-while-revalidate
|
||||
🔒 **Fiabilité** : Fonctionne même si Komga est lent ou inaccessible
|
||||
💾 **Flexibilité** : Mode mémoire ou fichier selon les besoins
|
||||
🚀 **Offline-first** : Support complet du mode hors ligne
|
||||
🧹 **Simplicité** : 3 couches bien définies, pas de redondance
|
||||
|
||||
Le système est maintenu simple avec des responsabilités claires pour chaque couche, facilitant la maintenance et l'évolution future.
|
||||
|
||||
Reference in New Issue
Block a user