# 🔍 DIAGNOSTIC COMPLET - Kafka & WebSocket Temps Réel **Date** : 28 janvier 2026 **Problème** : Messagerie, notifications et actualisations événementielles en temps réel ne fonctionnent pas avec Kafka --- ## 📋 RÉSUMÉ EXÉCUTIF L'architecture temps réel utilise Kafka comme bus de messages entre les services métier et les WebSockets. Plusieurs problèmes critiques empêchent le bon fonctionnement : 1. ❌ **Heartbeat non démarré** côté Flutter 2. ⚠️ **Serializers Kafka manquants** (Quarkus auto-génère mais peut échouer) 3. ⚠️ **Configuration Kafka incomplète** (bootstrap servers, health checks) 4. ⚠️ **WebSocket paths** avec root-path `/afterwork` 5. ⚠️ **Bridges Kafka** peuvent ne pas démarrer si Kafka indisponible --- ## 🔴 PROBLÈMES CRITIQUES IDENTIFIÉS ### 1. Heartbeat Non Démarré (Flutter) **Fichier** : `afterwork/lib/data/services/realtime_notification_service.dart` **Problème** : La méthode `_startHeartbeat()` existe mais n'est **jamais appelée** après une connexion réussie. **Ligne 88-101** : Après `_isConnected = true`, le heartbeat n'est pas démarré. **Impact** : - La connexion WebSocket peut timeout côté serveur - Le statut de présence n'est pas maintenu - Les notifications peuvent être perdues **Solution** : Appeler `_startHeartbeat()` après la connexion réussie. --- ### 2. Serializers Kafka Non Explicites **Fichier** : `application.properties` **Problème** : Les serializers/deserializers sont omis avec le commentaire "Quarkus génère automatiquement". Cependant : - Quarkus utilise Jackson pour sérialiser les DTOs - Les DTOs doivent être correctement annotés - En cas d'échec, les messages ne sont pas publiés dans Kafka **Solution** : Ajouter explicitement les serializers Jackson ou vérifier que les DTOs sont sérialisables. --- ### 3. Configuration Kafka Bootstrap Servers **Fichier** : `application.properties` et `application-prod.properties` **Problème** : - Production : `kafka-service.kafka.svc.cluster.local:9092` (Kubernetes DNS) - Dev : `localhost:9092` (override dans `application-dev.properties`) **Vérifications nécessaires** : - Kafka est-il déployé en production ? - Le service DNS `kafka-service.kafka.svc.cluster.local` est-il résolvable ? - Les health checks Kafka sont-ils activés ? **Solution** : Vérifier le déploiement Kafka et ajouter des health checks. --- ### 4. WebSocket Paths avec Root-Path **Fichier** : `application-prod.properties` **Problème** : `quarkus.http.root-path=/afterwork` est configuré. **Impact potentiel** : - Les WebSockets peuvent nécessiter le path complet : `wss://api.lions.dev/afterwork/notifications/{userId}` - Le frontend Flutter utilise : `ws://{baseUrl}/notifications/{userId}` **Vérification** : Tester si les WebSockets fonctionnent avec ou sans le root-path. --- ### 5. Bridges Kafka Peuvent Échouer Silencieusement **Fichiers** : `NotificationKafkaBridge.java`, `ChatKafkaBridge.java`, etc. **Problème** : Si Kafka n'est pas disponible au démarrage : - Les bridges peuvent ne pas démarrer - Aucune erreur visible si les exceptions sont catchées - Les messages sont perdus sans notification **Solution** : Ajouter des logs de démarrage et vérifier que les bridges sont actifs. --- ## 🟡 PROBLÈMES MOYENS ### 6. DTOs Événements Sans Annotations Jackson **Fichiers** : `NotificationEvent.java`, `ChatMessageEvent.java`, etc. **Problème** : Les DTOs utilisent Lombok mais peuvent manquer d'annotations Jackson pour la sérialisation JSON. **Solution** : Vérifier que les DTOs sont correctement sérialisables avec Jackson. --- ### 7. Gestion d'Erreurs Kafka Silencieuse **Fichiers** : `MessageService.java`, `EventService.java`, etc. **Problème** : Les erreurs Kafka sont catchées et loggées mais ne remontent pas : ```java } catch (Exception e) { System.out.println("[ERROR] Erreur lors de la publication dans Kafka : " + e.getMessage()); // Ne pas bloquer l'envoi du message si Kafka échoue } ``` **Impact** : Les messages sont sauvegardés en DB mais pas diffusés en temps réel, sans notification à l'utilisateur. --- ## ✅ CORRECTIONS À APPLIQUER ### Correction 1 : Démarrer le Heartbeat après Connexion **Fichier** : `afterwork/lib/data/services/realtime_notification_service.dart` ```dart _isConnected = true; _startHeartbeat(); // ← AJOUTER CETTE LIGNE if (!_isDisposed) { notifyListeners(); } ``` --- ### Correction 2 : Ajouter Serializers Kafka Explicites **Fichier** : `application.properties` Ajouter pour chaque topic outgoing : ```properties mp.messaging.outgoing.notifications.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer mp.messaging.outgoing.chat-messages.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer mp.messaging.outgoing.reactions.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer mp.messaging.outgoing.presence.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer ``` Et pour chaque topic incoming : ```properties mp.messaging.incoming.kafka-notifications.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer mp.messaging.incoming.kafka-chat.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer mp.messaging.incoming.kafka-reactions.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer mp.messaging.incoming.kafka-presence.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer ``` **Note** : Quarkus peut utiliser Jackson au lieu de Jsonb. Vérifier la dépendance dans `pom.xml`. --- ### Correction 3 : Vérifier les DTOs avec Annotations Jackson **Fichiers** : Tous les DTOs d'événements Ajouter si nécessaire : ```java import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class NotificationEvent { @JsonProperty("userId") private String userId; // ... } ``` --- ### Correction 4 : Ajouter Logs de Démarrage des Bridges **Fichiers** : Tous les bridges Kafka Ajouter dans chaque bridge : ```java @PostConstruct public void init() { Log.info("[KAFKA-BRIDGE] Bridge démarré pour topic: notifications"); } ``` --- ### Correction 5 : Améliorer la Gestion d'Erreurs Kafka **Fichiers** : Services qui publient dans Kafka Au lieu de : ```java } catch (Exception e) { System.out.println("[ERROR] Erreur Kafka"); } ``` Utiliser : ```java } catch (Exception e) { Log.error("[ERROR] Erreur publication Kafka", e); // Optionnel: Notifier l'utilisateur ou retry } ``` --- ## 🧪 TESTS DE VALIDATION ### Test 1 : Vérifier Connexion Kafka ```bash # En production (Kubernetes) kubectl exec -it kafka-pod -- kafka-console-consumer --bootstrap-server localhost:9092 --topic notifications --from-beginning ``` ### Test 2 : Vérifier WebSocket ```javascript // Dans la console navigateur const ws = new WebSocket('wss://api.lions.dev/afterwork/notifications/{userId}'); ws.onopen = () => console.log('Connected'); ws.onmessage = (e) => console.log('Message:', e.data); ``` ### Test 3 : Vérifier Heartbeat Flutter - Ouvrir les logs Flutter - Vérifier que des "Ping envoyé" apparaissent toutes les 30 secondes --- ## 📊 CHECKLIST DE VÉRIFICATION - [ ] Kafka est déployé et accessible - [ ] Les topics Kafka existent (`notifications`, `chat.messages`, `reactions`, `presence.updates`) - [ ] Les bridges Kafka démarrent sans erreur - [ ] Les WebSockets se connectent correctement - [ ] Le heartbeat Flutter fonctionne - [ ] Les messages sont publiés dans Kafka - [ ] Les messages sont routés vers WebSocket - [ ] Les clients reçoivent les notifications --- ## 🔗 RESSOURCES - [Quarkus Reactive Messaging Kafka](https://quarkus.io/guides/kafka) - [Quarkus WebSockets Next](https://quarkus.io/guides/websockets-next) - [SmallRye Reactive Messaging](https://smallrye.io/smallrye-reactive-messaging/)