prod: UI Optimisée mise en production
- Documentation archivée et réorganisée - Backend: Ajout tests, migrations, library service, rate limiting - Frontend: Suppression Flutter, focus sur interface web HTML/JS - Tailwind CSS ajouté pour le style - Améliorations UX et corrections bugs Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
@@ -0,0 +1,317 @@
|
||||
# Guide de Déploiement - Module Bibliothèque
|
||||
|
||||
## Checklist de Déploiement
|
||||
|
||||
### 1. Migration de la Base de Données
|
||||
|
||||
Le module bibliothèque nécessite deux nouvelles tables. Exécutez les commandes suivantes:
|
||||
|
||||
```bash
|
||||
cd /opt/audiOhm/backend
|
||||
|
||||
# Option 1: Utiliser Alembic (recommandé en production)
|
||||
alembic revision --autogenerate -m "Add library tables (listening_history, liked_tracks)"
|
||||
alembic upgrade head
|
||||
|
||||
# Option 2: Recréer la base (environnement de développement uniquement)
|
||||
# Attention: Cela efface toutes les données existantes!
|
||||
python -c "from app.core.database import init_db; import asyncio; asyncio.run(init_db())"
|
||||
```
|
||||
|
||||
### 2. Vérification de l'Installation
|
||||
|
||||
```bash
|
||||
# Exécuter les tests
|
||||
python3 test_library_features.py
|
||||
|
||||
# Vérifier que tous les tests passent (6/6)
|
||||
```
|
||||
|
||||
### 3. Redémarrage du Serveur
|
||||
|
||||
```bash
|
||||
# Arrêter le serveur existant
|
||||
pkill -f "uvicorn app.main:app"
|
||||
|
||||
# Démarrer le nouveau serveur
|
||||
cd /opt/audiOhm/backend
|
||||
python -m app.main
|
||||
# OU
|
||||
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
|
||||
```
|
||||
|
||||
### 4. Vérification des Endpoints
|
||||
|
||||
```bash
|
||||
# Vérifier que le serveur répond
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Vérifier la documentation OpenAPI
|
||||
curl http://localhost:8000/api/openapi.json | grep -A 5 "/api/v1/library"
|
||||
|
||||
# Tester un endpoint (nécessite un token JWT valide)
|
||||
curl -X GET http://localhost:8000/api/v1/library/stats \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
```
|
||||
|
||||
## Structure des Tables
|
||||
|
||||
### Table `listening_history`
|
||||
|
||||
```sql
|
||||
CREATE TABLE listening_history (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
track_id UUID NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
played_for INTEGER NOT NULL DEFAULT 0,
|
||||
completed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
source VARCHAR(50),
|
||||
played_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Index pour les requêtes fréquentes
|
||||
CREATE INDEX ix_listening_history_user_played
|
||||
ON listening_history(user_id, played_at DESC);
|
||||
|
||||
CREATE INDEX ix_listening_history_user_track
|
||||
ON listening_history(user_id, track_id);
|
||||
|
||||
CREATE INDEX ix_listening_history_user_id
|
||||
ON listening_history(user_id);
|
||||
|
||||
CREATE INDEX ix_listening_history_track_id
|
||||
ON listening_history(track_id);
|
||||
|
||||
CREATE INDEX ix_listening_history_played_at
|
||||
ON listening_history(played_at DESC);
|
||||
```
|
||||
|
||||
### Table `liked_tracks`
|
||||
|
||||
```sql
|
||||
CREATE TABLE liked_tracks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
track_id UUID NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
notes VARCHAR(1000),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT unique_user_track UNIQUE (user_id, track_id)
|
||||
);
|
||||
|
||||
-- Index pour les requêtes fréquentes
|
||||
CREATE INDEX ix_liked_tracks_user_track
|
||||
ON liked_tracks(user_id, track_id);
|
||||
|
||||
CREATE INDEX ix_liked_tracks_user_id
|
||||
ON liked_tracks(user_id);
|
||||
|
||||
CREATE INDEX ix_liked_tracks_track_id
|
||||
ON liked_tracks(track_id);
|
||||
|
||||
CREATE INDEX ix_liked_tracks_created_at
|
||||
ON liked_tracks(created_at DESC);
|
||||
```
|
||||
|
||||
## Configuration Requise
|
||||
|
||||
### Variables d'Environnement
|
||||
|
||||
Aucune variable d'environnement supplémentaire n'est requise. Le module utilise les variables existantes:
|
||||
- `DATABASE_URL`: Connection string PostgreSQL
|
||||
- `REDIS_URL` (optionnel): Pour le cache futur
|
||||
|
||||
### Dépendances Python
|
||||
|
||||
Toutes les dépendances sont déjà installées. Le module utilise:
|
||||
- `fastapi`: Framework API
|
||||
- `sqlalchemy`: ORM de base de données
|
||||
- `pydantic`: Validation des données
|
||||
- `asyncpg`: Driver PostgreSQL asynchrone
|
||||
|
||||
## Performance et Optimisation
|
||||
|
||||
### 1. Index de Base de Données
|
||||
|
||||
Les index sont déjà définis dans les modèles et seront créés automatiquement par Alembic.
|
||||
|
||||
### 2. Cache (Optionnel)
|
||||
|
||||
Pour améliorer les performances, vous pouvez ajouter du cache Redis:
|
||||
|
||||
```python
|
||||
# Dans library_service.py
|
||||
from app.core.cache import cache_manager
|
||||
|
||||
@cache_manager.cache(ttl=300) # Cache 5 minutes
|
||||
async def get_library_stats(self, user_id: UUID) -> dict:
|
||||
# ... code existant ...
|
||||
```
|
||||
|
||||
### 3. Partitionnement (Futur)
|
||||
|
||||
Pour les bases de données avec beaucoup d'historique, envisagez le partitionnement:
|
||||
|
||||
```sql
|
||||
-- Partitionnement mensuel de listening_history
|
||||
CREATE TABLE listening_history_2026_01 PARTITION OF listening_history
|
||||
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
|
||||
```
|
||||
|
||||
## Surveillance et Logs
|
||||
|
||||
### Métriques à Surveiller
|
||||
|
||||
1. **Nombre d'entrées d'historique par utilisateur**
|
||||
```sql
|
||||
SELECT user_id, COUNT(*) as total
|
||||
FROM listening_history
|
||||
GROUP BY user_id
|
||||
ORDER BY total DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
2. **Morceaux les plus likés**
|
||||
```sql
|
||||
SELECT track_id, COUNT(*) as like_count
|
||||
FROM liked_tracks
|
||||
GROUP BY track_id
|
||||
ORDER BY like_count DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
3. **Croissance de l'historique**
|
||||
```sql
|
||||
SELECT DATE(played_at) as date, COUNT(*) as count
|
||||
FROM listening_history
|
||||
GROUP BY DATE(played_at)
|
||||
ORDER BY date DESC
|
||||
LIMIT 30;
|
||||
```
|
||||
|
||||
### Alertes Recommandées
|
||||
|
||||
- Taille de la table `listening_history` > 1M entrées
|
||||
- Temps de réponse moyen des endpoints > 500ms
|
||||
- Erreurs 500 sur les endpoints de bibliothèque
|
||||
|
||||
## Sécurité
|
||||
|
||||
### Permissions
|
||||
|
||||
Tous les endpoints:
|
||||
- Nécessitent une authentification JWT valide
|
||||
- Vérifient que l'utilisateur accède uniquement à ses propres données
|
||||
- Utilisent des requêtes paramétrées pour prévenir les injections SQL
|
||||
|
||||
### Rate Limiting (Recommandé)
|
||||
|
||||
```python
|
||||
# Dans main.py
|
||||
from slowapi import Limiter
|
||||
from slowapi.util import get_remote_address
|
||||
|
||||
limiter = Limiter(key_func=get_remote_address)
|
||||
app.state.limiter = limiter
|
||||
|
||||
@router.get("/library/history")
|
||||
@limiter.limit("60/minute")
|
||||
async def get_listening_history(...):
|
||||
...
|
||||
```
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
En cas de problème, voici comment revenir en arrière:
|
||||
|
||||
### 1. Désactiver les Routes
|
||||
|
||||
```python
|
||||
# Dans main.py, commenter la ligne:
|
||||
# app.include_router(library.router, prefix=settings.API_V1_PREFIX, tags=["library"])
|
||||
```
|
||||
|
||||
### 2. Supprimer les Tables (si nécessaire)
|
||||
|
||||
```bash
|
||||
# Se connecter à PostgreSQL
|
||||
psql $DATABASE_URL
|
||||
|
||||
# Supprimer les tables
|
||||
DROP TABLE IF EXISTS listening_history CASCADE;
|
||||
DROP TABLE IF EXISTS liked_tracks CASCADE;
|
||||
```
|
||||
|
||||
### 3. Redémarrer le Serveur
|
||||
|
||||
```bash
|
||||
pkill -f "uvicorn app.main:app"
|
||||
python -m app.main
|
||||
```
|
||||
|
||||
## Tests Post-Déploiement
|
||||
|
||||
### 1. Tests Manuels
|
||||
|
||||
```bash
|
||||
# Récupérer un token JWT
|
||||
TOKEN=$(curl -X POST http://localhost:8000/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"test@example.com","password":"password"}' \
|
||||
| jq -r '.access_token')
|
||||
|
||||
# Tester les endpoints
|
||||
curl -X GET http://localhost:8000/api/v1/library/stats \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
|
||||
curl -X GET http://localhost:8000/api/v1/library/liked \
|
||||
-H "Authorization: Bearer $TOKEN"
|
||||
```
|
||||
|
||||
### 2. Tests Automatisés
|
||||
|
||||
```bash
|
||||
cd /opt/audiOhm/backend
|
||||
python3 test_library_features.py
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Tâches Planifiées
|
||||
|
||||
1. **Nettoyage de l'historique ancien** (optionnel)
|
||||
```python
|
||||
# Tâche mensuelle pour archiver/épurér les données > 1 an
|
||||
async def cleanup_old_history():
|
||||
cutoff = datetime.utcnow() - timedelta(days=365)
|
||||
await library_service.clear_listening_history(
|
||||
user_id=None, # Tous les utilisateurs
|
||||
before_date=cutoff
|
||||
)
|
||||
```
|
||||
|
||||
2. **Recalcul des statistiques** (si cache utilisé)
|
||||
```python
|
||||
# Tâche hebdomadaire
|
||||
async def refresh_stats_cache():
|
||||
# Invalider le cache des stats
|
||||
await cache_manager.clear_pattern("library_stats:*")
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
En cas de problème:
|
||||
|
||||
1. Vérifier les logs: `journalctl -u audiOhm-backend -f`
|
||||
2. Vérifier la connexion BD: `psql $DATABASE_URL`
|
||||
3. Exécuter les tests: `python3 test_library_features.py`
|
||||
4. Consulter la documentation: `LIBRARY_IMPLEMENTATION.md`
|
||||
|
||||
## Prochaine Étape
|
||||
|
||||
Une fois le déploiement réussi:
|
||||
1. Informer l'équipe frontend des nouveaux endpoints
|
||||
2. Partager le guide API: `LIBRARY_API_GUIDE.md`
|
||||
3. Surveiller les métriques pendant 24-48h
|
||||
4. Collecter les feedbacks utilisateurs
|
||||
Reference in New Issue
Block a user