Files
mic-after-work-server-impl-…/DIAGNOSTIC_KAFKA_WEBSOCKET.md

7.8 KiB

🔍 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 :

} 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

_isConnected = true;
_startHeartbeat(); // ← AJOUTER CETTE LIGNE
if (!_isDisposed) {
  notifyListeners();
}

Correction 2 : Ajouter Serializers Kafka Explicites

Fichier : application.properties

Ajouter pour chaque topic outgoing :

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 :

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 :

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 :

@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 :

} catch (Exception e) {
    System.out.println("[ERROR] Erreur Kafka");
}

Utiliser :

} 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

# En production (Kubernetes)
kubectl exec -it kafka-pod -- kafka-console-consumer --bootstrap-server localhost:9092 --topic notifications --from-beginning

Test 2 : Vérifier WebSocket

// 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