# language: fr Fonctionnalité: API - File d'attente et pré-calcul des contenus En tant qu'API backend Je veux pré-calculer et gérer la file d'attente de contenus Afin d'assurer une navigation fluide sans latence Contexte: Étant donné que l'API RoadWave est disponible Et que Redis est accessible Et que PostgreSQL avec PostGIS est accessible Et qu'un utilisateur "user123" existe avec token JWT valide # Pré-calcul initial Scénario: API pré-calcule 5 contenus au démarrage de session Étant donné que l'utilisateur "user123" démarre une session Et qu'il est situé à Paris (48.8566, 2.3522) Et qu'il est en mode voiture (vitesse ≥ 5 km/h) Quand je POST /api/v1/queue/initialize """json { "user_id": "user123", "latitude": 48.8566, "longitude": 2.3522, "mode": "voiture" } """ Alors le statut de réponse est 201 Et la réponse contient: """json { "queue_size": 5, "contents": [ {"id": "content1", "title": "...", "position": 1}, {"id": "content2", "title": "...", "position": 2}, {"id": "content3", "title": "...", "position": 3}, {"id": "content4", "title": "...", "position": 4}, {"id": "content5", "title": "...", "position": 5} ] } """ Et en Redis, la clé "user:user123:queue" contient 5 contenus Et les métadonnées incluent: | champ | valeur | | last_lat | 48.8566 | | last_lon | 2.3522 | | mode | voiture | | computed_at | (timestamp actuel) | Et le TTL est de 900 secondes (15 minutes) Scénario: API GET retourne la file d'attente en cache Étant donné qu'une file de 5 contenus existe en cache Redis pour "user123" Quand je GET /api/v1/queue Alors le statut de réponse est 200 Et la réponse contient les 5 contenus pré-calculés Et la latence de réponse est < 50ms (lecture Redis) Scénario: API retire un contenu de la file après lecture Étant donné qu'une file de 5 contenus [C1, C2, C3, C4, C5] existe pour "user123" Quand je POST /api/v1/queue/consume """json { "user_id": "user123", "content_id": "C1" } """ Alors le statut de réponse est 200 Et la file d'attente devient [C2, C3, C4, C5] Et la taille de la file est 4 # Recalcul automatique Scénario: API recalcule après déplacement >10km Étant donné qu'une file a été calculée à Paris (48.8566, 2.3522) Et que l'utilisateur se déplace à Versailles (48.8049, 2.1204) soit 12km Quand je POST /api/v1/queue/update-location """json { "user_id": "user123", "latitude": 48.8049, "longitude": 2.1204 } """ Alors le statut de réponse est 200 Et la réponse contient: """json { "queue_invalidated": true, "reason": "distance_threshold_exceeded", "distance_km": 12.1, "new_queue_size": 5 } """ Et la nouvelle file est basée sur la position Versailles Et l'ancienne file a été supprimée de Redis Scénario: API ne recalcule pas si déplacement ≤10km Étant donné qu'une file a été calculée à Paris (48.8566, 2.3522) Et que l'utilisateur se déplace de 8 km Quand je POST /api/v1/queue/update-location """json { "user_id": "user123", "latitude": 48.8500, "longitude": 2.3600 } """ Alors le statut de réponse est 200 Et la réponse contient: """json { "queue_invalidated": false, "distance_km": 8.2, "threshold": 10 } """ Et la file en cache reste inchangée Scénario: API recalcule après 10 minutes Étant donné qu'une file a été calculée à 10:00:00 Et que l'heure actuelle est 10:10:01 Quand je GET /api/v1/queue Alors le statut de réponse est 200 Et la réponse contient: """json { "queue_invalidated": true, "reason": "time_threshold_exceeded", "elapsed_minutes": 10, "new_queue_size": 5 } """ Et une nouvelle file de 5 contenus est recalculée Et le timestamp "computed_at" est mis à jour Scénario: API recalcule quand il reste <3 contenus Étant donné qu'il reste 3 contenus [C3, C4, C5] dans la file Quand je POST /api/v1/queue/consume (consomme C3) Alors le statut de réponse est 200 Et la file devient [C4, C5] Et un recalcul asynchrone est déclenché Et 3 nouveaux contenus [C6, C7, C8] sont ajoutés Et la file finale est [C4, C5, C6, C7, C8] # Invalidation immédiate Scénario: API invalide après modification préférences utilisateur Étant donné qu'une file de 5 contenus existe pour "user123" Et que l'utilisateur est en mode piéton (vitesse < 5 km/h) Quand je PUT /api/v1/users/user123/preferences """json { "geo_radius": 20, "discovery_factor": 0.7, "political_content": false } """ Alors le statut de réponse est 200 Et la file d'attente est invalidée immédiatement Et une nouvelle file est recalculée avec les nouvelles préférences Et en Redis, l'ancienne file a été supprimée Scénario: API refuse modification préférences si vitesse >10 km/h Étant donné que l'utilisateur roule à 50 km/h Quand je PUT /api/v1/users/user123/preferences """json { "geo_radius": 30 } """ Alors le statut de réponse est 403 Et la réponse contient: """json { "error": "MODIFICATION_BLOCKED_WHILE_DRIVING", "message": "Modification des préférences interdite en conduite (vitesse > 10 km/h)", "current_speed_kmh": 50 } """ Et les préférences ne sont pas modifiées Scénario: API invalide après démarrage live d'un créateur suivi Étant donné que l'utilisateur "user123" suit le créateur "creator456" Et qu'une file de 5 contenus existe Et que l'utilisateur est dans la zone du créateur Quand le créateur "creator456" démarre un live Alors une notification push est envoyée à "user123" Et la file d'attente est recalculée Et le contenu live est inséré en tête de file Et la nouvelle file commence par le live # Métadonnées et persistence Scénario: API stocke métadonnées complètes en Redis Étant donné qu'une file est calculée à 10:30:00 Quand je consulte Redis avec la clé "user:user123:queue" Alors la structure est: """json { "contents": [ {"id": "C1", "position": 1}, {"id": "C2", "position": 2}, {"id": "C3", "position": 3}, {"id": "C4", "position": 4}, {"id": "C5", "position": 5} ], "metadata": { "last_lat": 48.8566, "last_lon": 2.3522, "computed_at": "2026-02-02T10:30:00Z", "mode": "voiture" } } """ Et le TTL est exactement 900 secondes Scénario: API calcule distance avec PostGIS Étant donné que l'ancienne position est Paris (48.8566, 2.3522) Et que la nouvelle position est Versailles (48.8049, 2.1204) Quand l'API calcule la distance Alors la requête SQL utilise: """sql SELECT ST_Distance( ST_MakePoint(2.3522, 48.8566)::geography, ST_MakePoint(2.1204, 48.8049)::geography ) / 1000 AS distance_km """ Et le résultat est 12.1 km # Gestion erreurs Scénario: API gère échec Redis gracieusement Étant donné que Redis est indisponible Quand je GET /api/v1/queue Alors le statut de réponse est 503 Et la réponse contient: """json { "error": "CACHE_UNAVAILABLE", "message": "Service de cache temporairement indisponible", "fallback": "Calcul direct sans cache" } """ Et une nouvelle file est calculée directement depuis PostgreSQL Scénario: API gère aucun contenu disponible Étant donné qu'aucun contenu n'existe dans la zone de l'utilisateur Quand je POST /api/v1/queue/initialize Alors le statut de réponse est 200 Et la réponse contient: """json { "queue_size": 0, "contents": [], "message": "Aucun contenu disponible dans cette zone", "suggested_action": "expand_radius" } """ Scénario: API élargit la zone de recherche si aucun contenu Étant donné qu'aucun contenu n'existe dans un rayon de 20km Quand je POST /api/v1/queue/expand-radius """json { "user_id": "user123", "additional_radius_km": 50 } """ Alors le statut de réponse est 200 Et la recherche utilise un rayon de 70km (20 + 50) Et une nouvelle file est calculée avec ce rayon # Performance Scénario: API répond en <100ms pour lecture cache Étant donné qu'une file existe en Redis Quand je GET /api/v1/queue à 10:30:00.000 Alors la réponse est reçue à 10:30:00.050 (50ms) Et la latence est < 100ms Scénario: API recalcule en arrière-plan sans bloquer Étant donné qu'il reste 2 contenus dans la file Quand je POST /api/v1/queue/consume Alors le statut de réponse est 200 (immédiat) Et la réponse est retournée en < 100ms Et le recalcul asynchrone démarre en parallèle Et le client ne perçoit aucune latence Plan du Scénario: Conditions de recalcul selon distance Étant donné qu'une file a été calculée à une position donnée Quand l'utilisateur se déplace de km Alors la file est Exemples: | distance | action | | 5 | conservée | | 9.9 | conservée | | 10.0 | conservée | | 10.1 | invalidée et recalculée | | 15 | invalidée et recalculée | | 50 | invalidée et recalculée | Plan du Scénario: Conditions de recalcul selon temps écoulé Étant donné qu'une file a été calculée il y a minutes Quand je consulte la file Alors la file est Exemples: | temps | action | | 5 | conservée | | 9 | conservée | | 10 | invalidée et recalculée | | 15 | invalidée et recalculée | | 60 | invalidée et recalculée |