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

@@ -81,25 +81,30 @@ public class ChatWebSocketNext {
String userId = connection.pathParam("userId");
Log.debug("[CHAT-WS-NEXT] Message reçu de " + userId + ": " + message);
// Parser le message JSON
com.fasterxml.jackson.databind.ObjectMapper mapper =
new com.fasterxml.jackson.databind.ObjectMapper();
Map<String, Object> messageData = mapper.readValue(message, Map.class);
String type = (String) messageData.get("type");
Map<String, Object> raw = mapper.readValue(message, Map.class);
String type = (String) raw.get("type");
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) raw.get("data");
switch (type) {
case "message":
handleChatMessage(messageData, userId);
if (data != null) handleChatMessage(data, userId);
else Log.warn("[CHAT-WS-NEXT] Message sans 'data'");
break;
case "typing":
handleTypingIndicator(messageData, userId);
if (data != null) handleTypingIndicator(data, userId);
break;
case "read":
handleReadReceipt(messageData, userId);
if (data != null) handleReadReceipt(data, userId);
else Log.warn("[CHAT-WS-NEXT] Read receipt sans 'data'");
break;
case "ping":
// Heartbeat - ignorer
break;
default:
Log.warn("[CHAT-WS-NEXT] Type de message inconnu: " + type);
Log.warn("[CHAT-WS-NEXT] Type inconnu: " + type);
}
} catch (Exception e) {
@@ -108,16 +113,17 @@ public class ChatWebSocketNext {
}
/**
* Gère l'envoi d'un message de chat.
* Le message est traité par MessageService qui publiera dans Kafka.
* Gère l'envoi d'un message de chat via WebSocket.
* Note: L'envoi principal passe par REST (POST /messages). Cette méthode
* est pour compatibilité si le client envoie via WebSocket.
*/
private void handleChatMessage(Map<String, Object> messageData, String senderId) {
private void handleChatMessage(Map<String, Object> data, String senderId) {
try {
UUID senderUUID = UUID.fromString(senderId);
UUID recipientUUID = UUID.fromString((String) messageData.get("recipientId"));
String content = (String) messageData.get("content");
String messageType = messageData.getOrDefault("messageType", "text").toString();
String mediaUrl = (String) messageData.get("mediaUrl");
UUID recipientUUID = UUID.fromString((String) data.get("recipientId"));
String content = (String) data.get("content");
String messageType = data.getOrDefault("messageType", "text").toString();
String mediaUrl = (String) data.get("mediaUrl");
// Enregistrer le message dans la base de données
// MessageService publiera automatiquement dans Kafka
@@ -146,13 +152,21 @@ public class ChatWebSocketNext {
/**
* Gère les indicateurs de frappe.
* data doit contenir recipientId (ID du destinataire) et isTyping.
*/
private void handleTypingIndicator(Map<String, Object> messageData, String userId) {
private void handleTypingIndicator(Map<String, Object> data, String userId) {
try {
UUID recipientUUID = UUID.fromString((String) messageData.get("recipientId"));
boolean isTyping = (boolean) messageData.getOrDefault("isTyping", false);
Object recipientIdObj = data.get("recipientId");
if (recipientIdObj == null) {
Log.warn("[CHAT-WS-NEXT] Typing sans recipientId - ignoré");
return;
}
UUID recipientUUID = UUID.fromString(recipientIdObj.toString());
Object isTypingObj = data.get("isTyping");
boolean isTyping = isTypingObj instanceof Boolean ? (Boolean) isTypingObj : Boolean.parseBoolean(String.valueOf(isTypingObj));
String response = buildJsonMessage("typing", Map.of(
"conversationId", data.getOrDefault("conversationId", ""),
"userId", userId,
"isTyping", isTyping
));
@@ -168,22 +182,22 @@ public class ChatWebSocketNext {
/**
* Gère les confirmations de lecture.
* Envoie type "read" (format attendu par le client Flutter).
*/
private void handleReadReceipt(Map<String, Object> messageData, String userId) {
private void handleReadReceipt(Map<String, Object> data, String userId) {
try {
UUID messageUUID = UUID.fromString((String) messageData.get("messageId"));
UUID messageUUID = UUID.fromString((String) data.get("messageId"));
// Marquer le message comme lu
Message message = messageService.markMessageAsRead(messageUUID);
if (message != null) {
// Envoyer confirmation de lecture à l'expéditeur via WebSocket
// (sera aussi publié dans Kafka par MessageService)
UUID senderUUID = message.getSender().getId();
String response = buildJsonMessage("read_receipt", Map.of(
long now = System.currentTimeMillis();
String timestampIso = java.time.Instant.ofEpochMilli(now).toString();
String response = buildJsonMessage("read", Map.of(
"messageId", messageUUID.toString(),
"readBy", userId,
"readAt", System.currentTimeMillis()
"userId", userId,
"timestamp", timestampIso
));
sendToUser(senderUUID, response);