feat: v2.0 – réorg docker/scripts, prod, résas, abonnements Wave, Flyway base vierge
This commit is contained in:
257
DIAGNOSTIC_KAFKA_WEBSOCKET.md
Normal file
257
DIAGNOSTIC_KAFKA_WEBSOCKET.md
Normal file
@@ -0,0 +1,257 @@
|
||||
# 🔍 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/)
|
||||
Reference in New Issue
Block a user