feat: v2.0 – réorg docker/scripts, prod, résas, abonnements Wave, Flyway base vierge

This commit is contained in:
dahoud
2026-01-29 00:44:40 +00:00
parent 9d5e388efa
commit ce89face73
66 changed files with 2333 additions and 227 deletions

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