feat(bdd): réorganiser features en catégories api/ui/e2e et créer ADR-024
Résolution des incohérences #10, #11, et #12 de l'analyse d'architecture. ## Phase 1 : Réorganisation Features BDD (Point #10 - RÉSOLU) - Créer structure features/{api,ui,e2e} - Déplacer 83 features en 3 catégories via git mv (historique préservé) - features/api/ : 53 features (tests API backend) - features/ui/ : 22 features (tests UI mobile) - features/e2e/ : 8 features (tests end-to-end) Domaines déplacés : - API : authentication, recommendation, rgpd-compliance, content-creation, moderation, monetisation, premium, radio-live, publicites - UI : audio-guides, navigation, interest-gauges, mode-offline, partage, profil, recherche - E2E : abonnements, error-handling ## Phase 2 : Mise à jour Documentation ### ADR-007 - Tests BDD - Ajouter section "Convention de Catégorisation des Features" - Documenter règles api/ui/e2e avec exemples concrets - Spécifier step definitions (backend Go, mobile Dart) ### ADR-024 - Stratégie CI/CD Monorepo (NOUVEAU) - Créer ADR dédié pour stratégie CI/CD avec path filters - Architecture workflows séparés (backend.yml, mobile.yml, shared.yml) - Configuration path filters détaillée avec exemples YAML - Matrice de déclenchement et optimisations (~70% gain temps CI) - Plan d'implémentation (~2h, reporté jusqu'au développement) ### ADR-016 - Organisation Monorepo - Simplifier en retirant section CI/CD détaillée - Ajouter référence vers ADR-024 pour stratégie CI/CD ### INCONSISTENCIES-ANALYSIS.md - Point #10 (Tests BDD synchronisés) : ✅ RÉSOLU - Catégorisation features implémentée - ADR-007 mis à jour avec convention complète - Point #11 (70/30 Split paiements) : ✅ ANNULÉ (faux problème) - ADR-009 et Règle 18 parfaitement cohérents - Documentation exhaustive existante (formule, SQL, comparaisons) - Point #12 (Monorepo path filters) : ⏸️ DOCUMENTÉ - Architecture CI/CD complète dans ADR-024 - Implémentation reportée (projet en phase documentation) - Métriques mises à jour : - MODERATE : 6/9 traités (4 résolus + 1 annulé + 1 documenté) - ADR à jour : 100% (19/19 avec ADR-024) ## Phase 3 : Validation - Structure features validée (api/ui/e2e, aucun répertoire restant) - Historique Git préservé (git mv, renommages détectés) - 83 features total (API: 53, UI: 22, E2E: 8) Closes: Point #10 (résolu), Point #11 (annulé), Point #12 (documenté) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
197
features/api/radio-live/architecture-technique-live.feature
Normal file
197
features/api/radio-live/architecture-technique-live.feature
Normal file
@@ -0,0 +1,197 @@
|
||||
# language: fr
|
||||
Fonctionnalité: Architecture technique radio live
|
||||
En tant que système
|
||||
Je veux gérer efficacement les flux audio en temps réel
|
||||
Afin d'assurer une diffusion stable et scalable des lives
|
||||
|
||||
Contexte:
|
||||
Étant donné que l'infrastructure RoadWave est opérationnelle
|
||||
Et que les serveurs Go avec Pion WebRTC sont actifs
|
||||
|
||||
Scénario: Ingestion WebRTC du flux créateur
|
||||
Étant donné qu'un créateur démarre un live depuis son application mobile
|
||||
Quand le flux audio WebRTC (Opus 48 kbps) arrive sur le serveur
|
||||
Alors le serveur Go avec Pion WebRTC accepte la connexion
|
||||
Et le flux est traité en temps réel
|
||||
|
||||
Scénario: Conversion temps réel Opus vers segments HLS
|
||||
Étant donné qu'un flux WebRTC Opus est reçu par le serveur
|
||||
Quand le serveur traite le flux
|
||||
Alors FFmpeg convertit en segments HLS (.ts)
|
||||
Et un fichier manifest .m3u8 est généré et mis à jour régulièrement
|
||||
Et les segments ont une durée de 2 secondes chacun
|
||||
|
||||
Scénario: Distribution via NGINX Cache
|
||||
Étant donné que les segments HLS sont générés
|
||||
Quand un auditeur demande à rejoindre le live
|
||||
Alors le manifest .m3u8 est servi via NGINX Cache (OVH)
|
||||
Et les segments .ts sont cachés sur le cache NGINX
|
||||
Et la distribution est globale avec latence minimale
|
||||
|
||||
Scénario: Lecture HLS native sur mobile iOS
|
||||
Étant donné qu'un auditeur iOS rejoint un live
|
||||
Quand l'application charge le flux HLS
|
||||
Alors le player natif AVPlayer gère la lecture
|
||||
Et le buffer de 15 secondes est appliqué automatiquement
|
||||
Et la qualité s'adapte selon la connexion
|
||||
|
||||
Scénario: Lecture HLS native sur mobile Android
|
||||
Étant donné qu'un auditeur Android rejoint un live
|
||||
Quand l'application charge le flux HLS
|
||||
Alors le player natif ExoPlayer gère la lecture
|
||||
Et le buffer de 15 secondes est configuré
|
||||
Et la qualité s'adapte selon la connexion
|
||||
|
||||
Scénario: Enregistrement parallèle du flux pour replay
|
||||
Étant donné qu'un live est en cours
|
||||
Alors un processus parallèle enregistre le flux Opus raw
|
||||
Et l'enregistrement est stocké temporairement sur le serveur
|
||||
Et l'enregistrement est indépendant de la diffusion HLS
|
||||
|
||||
Scénario: Traitement post-live asynchrone
|
||||
Étant donné qu'un live vient de se terminer
|
||||
Quand le processus post-live démarre
|
||||
Alors un job asynchrone est créé dans la queue Redis
|
||||
Et un worker Go récupère le job
|
||||
Et le worker exécute FFmpeg pour les conversions
|
||||
|
||||
Scénario: Conversion Opus raw vers MP3 256 kbps
|
||||
Étant donné qu'un worker traite un job post-live
|
||||
Quand la conversion démarre
|
||||
Alors FFmpeg convertit Opus raw en MP3 256 kbps
|
||||
Et la normalisation audio à -14 LUFS est appliquée
|
||||
Et les silences prolongés (>3 secondes) sont détectés et nettoyés
|
||||
|
||||
Scénario: Génération segments HLS pour le replay
|
||||
Étant donné que le MP3 256 kbps est généré
|
||||
Quand le worker crée les segments HLS
|
||||
Alors des segments .ts de 10 secondes sont créés
|
||||
Et un manifest .m3u8 est généré
|
||||
Et les segments sont uploadés vers OVH Object Storage
|
||||
|
||||
Scénario: Publication automatique du replay
|
||||
Étant donné que tous les segments HLS sont uploadés
|
||||
Quand le worker finalise le job
|
||||
Alors une entrée de contenu "replay" est créée en base PostgreSQL
|
||||
Et le titre est "[REPLAY] [Titre live original]"
|
||||
Et le type géographique est "Géo-neutre"
|
||||
Et le replay est immédiatement disponible pour les auditeurs
|
||||
|
||||
Scénario: Suppression automatique fichier Opus raw après 7 jours
|
||||
Étant donné qu'un replay est publié depuis 7 jours
|
||||
Quand le job de nettoyage quotidien s'exécute
|
||||
Alors le fichier Opus raw est supprimé du stockage
|
||||
Et seul le MP3 256 kbps et les segments HLS sont conservés
|
||||
Et l'espace de stockage est libéré
|
||||
|
||||
Scénario: Scalabilité horizontale des workers de conversion
|
||||
Étant donné que 50 lives se terminent simultanément
|
||||
Quand les jobs post-live sont créés
|
||||
Alors les workers Go disponibles traitent les jobs en parallèle
|
||||
Et si tous les workers sont occupés, les jobs attendent en queue Redis
|
||||
Et de nouveaux workers peuvent être lancés automatiquement (Kubernetes)
|
||||
|
||||
Scénario: Limitation du nombre de lives simultanés (MVP)
|
||||
Étant donné que l'infrastructure MVP est configurée pour 100 lives simultanés
|
||||
Et que 100 lives sont actuellement en cours
|
||||
Quand un nouveau créateur essaie de démarrer un live
|
||||
Alors la demande est refusée avec le code erreur 503
|
||||
Et le message "Capacité maximale atteinte. Veuillez réessayer dans quelques minutes" est retourné
|
||||
Et la demande peut être mise en queue prioritaire si créateur Premium
|
||||
|
||||
Scénario: Monitoring des ressources serveur en temps réel
|
||||
Étant donné que plusieurs lives sont en cours
|
||||
Alors le système monitore en temps réel:
|
||||
| métrique | seuil alerte |
|
||||
| CPU utilisation | >80% |
|
||||
| Mémoire utilisation | >85% |
|
||||
| Bande passante upload | >80% capacité|
|
||||
| Nombre connexions WebRTC | >90 |
|
||||
| Latence moyenne CDN | >200ms |
|
||||
Et si un seuil est dépassé, une alerte est envoyée à l'équipe technique
|
||||
|
||||
Scénario: Calcul du coût de bande passante CDN
|
||||
Étant donné qu'un live a 100 auditeurs simultanés
|
||||
Et que la qualité est 48 kbps Opus
|
||||
Quand le live dure 1 heure
|
||||
Alors la bande passante totale est d'environ 2.16 GB
|
||||
Et le coût estimé infrastructure est d'environ 0.02€
|
||||
Et ces métriques sont enregistrées pour facturation créateur si nécessaire
|
||||
|
||||
Scénario: Cache NGINX des segments HLS
|
||||
Étant donné qu'un live est diffusé via NGINX Cache
|
||||
Quand un segment .ts est généré
|
||||
Alors le segment est uploadé vers OVH Object Storage origin
|
||||
Et NGINX Cache met en cache le segment
|
||||
Et les auditeurs suivants récupèrent le segment depuis le cache
|
||||
Et la charge sur le serveur origin est réduite de ~90%
|
||||
|
||||
Scénario: Gestion de la latence WebRTC créateur
|
||||
Étant donné qu'un créateur diffuse avec une connexion 4G
|
||||
Quand la latence réseau augmente ponctuellement
|
||||
Alors le buffer côté serveur absorbe les fluctuations
|
||||
Et la qualité peut être réduite temporairement (48 kbps → 32 kbps)
|
||||
Et un warning est affiché au créateur si la connexion est trop instable
|
||||
|
||||
Scénario: Détection automatique de la musique protégée (post-MVP)
|
||||
Étant donné qu'un live contient de la musique en arrière-plan
|
||||
Quand le système d'audio fingerprint analyse le flux
|
||||
Alors une empreinte audio est calculée toutes les 30 secondes
|
||||
Et l'empreinte est comparée à une base de données de contenus protégés
|
||||
Et si une correspondance est trouvée, un warning est envoyé au créateur
|
||||
Et si le créateur ne corrige pas sous 30 secondes, le live peut être arrêté
|
||||
|
||||
Scénario: Stockage des métadonnées de live en PostgreSQL
|
||||
Étant donné qu'un créateur démarre un live
|
||||
Alors les métadonnées suivantes sont enregistrées:
|
||||
| champ | exemple valeur |
|
||||
| live_id | uuid v4 |
|
||||
| creator_id | uuid créateur |
|
||||
| title | "Mon super live" |
|
||||
| started_at | timestamp UTC |
|
||||
| zone_geo | "Île-de-France" |
|
||||
| tags | ["Actualité", "Tech"] |
|
||||
| classification_age | "Tout public" |
|
||||
Et ces données sont indexées pour recherche et analytics
|
||||
|
||||
Scénario: Cache Redis pour compteurs temps réel
|
||||
Étant donné qu'un live est en cours
|
||||
Alors Redis stocke les compteurs temps réel:
|
||||
| clé Redis | valeur exemple |
|
||||
| live:[live_id]:listeners | 247 |
|
||||
| live:[live_id]:likes | 89 |
|
||||
| live:[live_id]:reports | 0 |
|
||||
Et ces compteurs sont mis à jour toutes les 2 secondes
|
||||
Et les compteurs sont persistés en PostgreSQL toutes les 60 secondes
|
||||
|
||||
Scénario: Heartbeat auditeurs pour compteur précis
|
||||
Étant donné qu'un auditeur écoute un live
|
||||
Alors l'application envoie un heartbeat toutes les 10 secondes
|
||||
Et le heartbeat met à jour le timestamp dans Redis
|
||||
Et si aucun heartbeat n'est reçu pendant 30 secondes, l'auditeur est retiré du compteur
|
||||
|
||||
Scénario: Gestion des pannes serveur pendant un live
|
||||
Étant donné qu'un live est en cours sur serveur A
|
||||
Quand le serveur A tombe en panne
|
||||
Alors Kubernetes redémarre automatiquement un pod
|
||||
Mais le live en cours est perdu (pas de failover temps réel en MVP)
|
||||
Et le créateur voit le message "Connexion perdue. Veuillez redémarrer le live"
|
||||
Et les auditeurs voient "Le live est terminé suite à un problème technique"
|
||||
|
||||
Scénario: Backup automatique des enregistrements live
|
||||
Étant donné qu'un live est enregistré en Opus raw
|
||||
Quand l'enregistrement dépasse 10 minutes
|
||||
Alors un backup incrémental est créé toutes les 10 minutes
|
||||
Et le backup est stocké sur un stockage secondaire (S3-compatible)
|
||||
Et en cas de crash serveur, le live peut être récupéré jusqu'au dernier backup
|
||||
|
||||
Scénario: Logs et audit trail des lives
|
||||
Étant donné qu'un live démarre, se déroule et se termine
|
||||
Alors tous les événements sont loggés:
|
||||
| événement | détails enregistrés |
|
||||
| Démarrage live | timestamp, creator_id, zone_geo |
|
||||
| Auditeur rejoint | timestamp, user_id, position GPS |
|
||||
| Auditeur quitte | timestamp, user_id, durée écoute |
|
||||
| Signalement | timestamp, user_id, catégorie |
|
||||
| Fin live | timestamp, durée totale, stats finales |
|
||||
Et ces logs sont conservés 90 jours pour analytics et conformité RGPD
|
||||
Reference in New Issue
Block a user