Refactoring

This commit is contained in:
dahoud
2026-01-21 19:16:24 +00:00
parent b9fc1ee05a
commit 8cb67f1762
6 changed files with 66 additions and 108 deletions

View File

@@ -9,6 +9,7 @@ import org.eclipse.microprofile.reactive.messaging.Message;
import java.util.UUID; import java.util.UUID;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletionStage;
/** /**
* Bridge qui consomme depuis Kafka et envoie via WebSocket pour le chat. * Bridge qui consomme depuis Kafka et envoie via WebSocket pour le chat.
@@ -21,9 +22,12 @@ public class ChatKafkaBridge {
/** /**
* Consomme les messages chat depuis Kafka et les route vers WebSocket. * Consomme les messages chat depuis Kafka et les route vers WebSocket.
*
* @param message Message Kafka contenant un ChatMessageEvent
* @return CompletionStage pour gérer l'ack/nack asynchrone
*/ */
@Incoming("kafka-chat") @Incoming("kafka-chat")
public void processChatMessage(Message<ChatMessageEvent> message) { public CompletionStage<Void> processChatMessage(Message<ChatMessageEvent> message) {
try { try {
ChatMessageEvent event = message.getPayload(); ChatMessageEvent event = message.getPayload();
@@ -38,17 +42,17 @@ public class ChatKafkaBridge {
// Envoyer via WebSocket au destinataire // Envoyer via WebSocket au destinataire
ChatWebSocketNext.sendMessageToUser(recipientId, wsMessage); ChatWebSocketNext.sendMessageToUser(recipientId, wsMessage);
// Acknowledger le message Kafka
message.ack();
Log.debug("[CHAT-BRIDGE] Message routé vers WebSocket pour: " + event.getRecipientId()); Log.debug("[CHAT-BRIDGE] Message routé vers WebSocket pour: " + event.getRecipientId());
// Acknowledger le message Kafka
return message.ack();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.error("[CHAT-BRIDGE] UUID invalide dans l'événement", e); Log.error("[CHAT-BRIDGE] UUID invalide dans l'événement", e);
message.nack(e); return message.nack(e);
} catch (Exception e) { } catch (Exception e) {
Log.error("[CHAT-BRIDGE] Erreur traitement événement", e); Log.error("[CHAT-BRIDGE] Erreur traitement événement", e);
message.nack(e); return message.nack(e);
} }
} }

View File

@@ -8,6 +8,8 @@ import org.eclipse.microprofile.reactive.messaging.Incoming;
import org.eclipse.microprofile.reactive.messaging.Message; import org.eclipse.microprofile.reactive.messaging.Message;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
/** /**
* Bridge qui consomme depuis Kafka et envoie via WebSocket pour les notifications. * Bridge qui consomme depuis Kafka et envoie via WebSocket pour les notifications.
@@ -27,9 +29,10 @@ public class NotificationKafkaBridge {
* Consomme les événements depuis Kafka et les route vers WebSocket. * Consomme les événements depuis Kafka et les route vers WebSocket.
* *
* @param message Message Kafka contenant un NotificationEvent * @param message Message Kafka contenant un NotificationEvent
* @return CompletionStage pour gérer l'ack/nack asynchrone
*/ */
@Incoming("kafka-notifications") @Incoming("kafka-notifications")
public void processNotification(Message<NotificationEvent> message) { public CompletionStage<Void> processNotification(Message<NotificationEvent> message) {
try { try {
NotificationEvent event = message.getPayload(); NotificationEvent event = message.getPayload();
@@ -44,17 +47,17 @@ public class NotificationKafkaBridge {
// Envoyer via WebSocket // Envoyer via WebSocket
NotificationWebSocketNext.sendToUser(userId, wsMessage); NotificationWebSocketNext.sendToUser(userId, wsMessage);
// Acknowledger le message Kafka
message.ack();
Log.debug("[KAFKA-BRIDGE] Notification routée vers WebSocket pour: " + event.getUserId()); Log.debug("[KAFKA-BRIDGE] Notification routée vers WebSocket pour: " + event.getUserId());
// Acknowledger le message Kafka
return message.ack();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.error("[KAFKA-BRIDGE] UUID invalide dans l'événement", e); Log.error("[KAFKA-BRIDGE] UUID invalide dans l'événement", e);
message.nack(e); return message.nack(e);
} catch (Exception e) { } catch (Exception e) {
Log.error("[KAFKA-BRIDGE] Erreur traitement événement", e); Log.error("[KAFKA-BRIDGE] Erreur traitement événement", e);
message.nack(e); return message.nack(e);
} }
} }

View File

@@ -8,6 +8,7 @@ import org.eclipse.microprofile.reactive.messaging.Incoming;
import org.eclipse.microprofile.reactive.messaging.Message; import org.eclipse.microprofile.reactive.messaging.Message;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletionStage;
/** /**
* Bridge qui consomme depuis Kafka et envoie via WebSocket pour les réactions. * Bridge qui consomme depuis Kafka et envoie via WebSocket pour les réactions.
@@ -23,9 +24,12 @@ public class ReactionKafkaBridge {
/** /**
* Consomme les réactions depuis Kafka et les route vers WebSocket. * Consomme les réactions depuis Kafka et les route vers WebSocket.
*
* @param message Message Kafka contenant un ReactionEvent
* @return CompletionStage pour gérer l'ack/nack asynchrone
*/ */
@Incoming("kafka-reactions") @Incoming("kafka-reactions")
public void processReaction(Message<ReactionEvent> message) { public CompletionStage<Void> processReaction(Message<ReactionEvent> message) {
try { try {
ReactionEvent event = message.getPayload(); ReactionEvent event = message.getPayload();
@@ -50,14 +54,14 @@ public class ReactionKafkaBridge {
} }
// Acknowledger le message Kafka // Acknowledger le message Kafka
message.ack(); return message.ack();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
Log.error("[REACTION-BRIDGE] UUID invalide dans l'événement", e); Log.error("[REACTION-BRIDGE] UUID invalide dans l'événement", e);
message.nack(e); return message.nack(e);
} catch (Exception e) { } catch (Exception e) {
Log.error("[REACTION-BRIDGE] Erreur traitement événement", e); Log.error("[REACTION-BRIDGE] Erreur traitement événement", e);
message.nack(e); return message.nack(e);
} }
} }

View File

@@ -1,78 +0,0 @@
# ====================================================================
# AfterWork Server - Configuration PRODUCTION
# ====================================================================
# Ce fichier est automatiquement chargé avec: java -jar app.jar
# Les configurations ici surchargent celles de application.properties
# ====================================================================
# HTTP - Chemin de base de l'API
# ====================================================================
# Permet d'accéder à l'API via https://api.lions.dev/afterwork
quarkus.http.root-path=/afterwork
# ====================================================================
# Base de données PostgreSQL
# ====================================================================
quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST:postgresql}:${DB_PORT:5432}/${DB_NAME:mic-after-work-server-impl-quarkus-main}
quarkus.datasource.username=${DB_USERNAME:lionsuser}
quarkus.datasource.password=${DB_PASSWORD:LionsUser2025!}
quarkus.datasource.jdbc.driver=org.postgresql.Driver
quarkus.datasource.jdbc.max-size=20
quarkus.datasource.jdbc.min-size=5
quarkus.datasource.devservices.enabled=false
# ====================================================================
# Hibernate ORM
# ====================================================================
quarkus.hibernate-orm.database.generation=update
quarkus.hibernate-orm.log.sql=false
quarkus.hibernate-orm.sql-load-script=no-file
quarkus.hibernate-orm.jdbc.statement-batch-size=20
# ====================================================================
# CORS (Cross-Origin Resource Sharing)
# ====================================================================
quarkus.http.cors=true
quarkus.http.cors.origins=https://afterwork.lions.dev
quarkus.http.cors.methods=GET,POST,PUT,DELETE,OPTIONS,PATCH
quarkus.http.cors.headers=accept,authorization,content-type,x-requested-with
quarkus.http.cors.exposed-headers=content-disposition
quarkus.http.cors.access-control-max-age=24H
quarkus.http.cors.access-control-allow-credentials=true
# ====================================================================
# Logging
# ====================================================================
quarkus.log.level=INFO
quarkus.log.console.enable=true
quarkus.log.console.format=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c{3.}] (%t) %s%e%n
quarkus.log.console.json=false
quarkus.log.category."com.lions.dev".level=INFO
quarkus.log.category."org.hibernate".level=WARN
quarkus.log.category."io.quarkus".level=INFO
# ====================================================================
# WebSocket
# ====================================================================
quarkus.websocket.max-frame-size=65536
# ====================================================================
# SSL/TLS (géré par le reverse proxy)
# ====================================================================
quarkus.http.ssl.certificate.files=
quarkus.http.ssl.certificate.key-files=
quarkus.http.insecure-requests=enabled
# ====================================================================
# Performance
# ====================================================================
quarkus.thread-pool.core-threads=2
quarkus.thread-pool.max-threads=16
quarkus.thread-pool.queue-size=100
# ====================================================================
# Localisation
# ====================================================================
quarkus.locales=fr-FR,en-US
quarkus.default-locale=fr-FR

View File

@@ -3,9 +3,6 @@
# ==================================================================== # ====================================================================
# Ce fichier est automatiquement chargé avec: java -jar app.jar # Ce fichier est automatiquement chargé avec: java -jar app.jar
# Les configurations ici surchargent celles de application.properties # Les configurations ici surchargent celles de application.properties
#
# NOTE: Ce fichier est utilisé quand le profil est "production"
# Pour le profil "prod", voir application-prod.properties
# ==================================================================== # ====================================================================
# HTTP - Chemin de base de l'API # HTTP - Chemin de base de l'API
@@ -58,7 +55,8 @@ quarkus.log.category."io.quarkus".level=INFO
# ==================================================================== # ====================================================================
# WebSocket # WebSocket
# ==================================================================== # ====================================================================
quarkus.websocket.max-frame-size=65536 # Note: La propriété quarkus.websocket.max-frame-size n'existe pas dans Quarkus 3.16
# Les WebSockets Next utilisent une configuration différente si nécessaire
# ==================================================================== # ====================================================================
# SSL/TLS (géré par le reverse proxy) # SSL/TLS (géré par le reverse proxy)

View File

@@ -5,6 +5,10 @@
# Les configurations spécifiques sont dans : # Les configurations spécifiques sont dans :
# - application-dev.properties (développement) # - application-dev.properties (développement)
# - application-prod.properties (production) # - application-prod.properties (production)
# - application-production.properties (production - profil "production")
#
# NOTE: Configuration datasource par défaut pour les tests
# Les profils dev/prod/production surchargent cette configuration
# ==================================================================== # ====================================================================
# Swagger/OpenAPI (commun à tous les environnements) # Swagger/OpenAPI (commun à tous les environnements)
@@ -19,6 +23,22 @@ quarkus.smallrye-openapi.path=/openapi
quarkus.http.host=0.0.0.0 quarkus.http.host=0.0.0.0
quarkus.http.port=8080 quarkus.http.port=8080
# ====================================================================
# Base de données (configuration par défaut pour les tests)
# ====================================================================
# Cette configuration est utilisée par défaut si aucun profil n'est spécifié
# Les profils dev/prod/production surchargent cette configuration
quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
quarkus.datasource.username=sa
quarkus.datasource.password=
quarkus.datasource.jdbc.driver=org.h2.Driver
quarkus.datasource.devservices.enabled=false
# Hibernate ORM (par défaut)
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=false
# ==================================================================== # ====================================================================
# Upload de fichiers (commun à tous les environnements) # Upload de fichiers (commun à tous les environnements)
# ==================================================================== # ====================================================================
@@ -40,53 +60,60 @@ kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
# ==================================================================== # ====================================================================
# Kafka Topics - Outgoing (Services → Kafka) # Kafka Topics - Outgoing (Services → Kafka)
# ==================================================================== # ====================================================================
# Note: Quarkus génère automatiquement les serializers Jackson basés sur le type Emitter<EventType>
# Topic: Notifications # Topic: Notifications
mp.messaging.outgoing.notifications.connector=smallrye-kafka mp.messaging.outgoing.notifications.connector=smallrye-kafka
mp.messaging.outgoing.notifications.topic=notifications mp.messaging.outgoing.notifications.topic=notifications
mp.messaging.outgoing.notifications.key.serializer=org.apache.kafka.common.serialization.StringSerializer mp.messaging.outgoing.notifications.key.serializer=org.apache.kafka.common.serialization.StringSerializer
mp.messaging.outgoing.notifications.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer # value.serializer omis - Quarkus génère automatiquement depuis Emitter<NotificationEvent>
# Topic: Chat Messages # Topic: Chat Messages
mp.messaging.outgoing.chat-messages.connector=smallrye-kafka mp.messaging.outgoing.chat-messages.connector=smallrye-kafka
mp.messaging.outgoing.chat-messages.topic=chat.messages mp.messaging.outgoing.chat-messages.topic=chat.messages
mp.messaging.outgoing.chat-messages.key.serializer=org.apache.kafka.common.serialization.StringSerializer mp.messaging.outgoing.chat-messages.key.serializer=org.apache.kafka.common.serialization.StringSerializer
mp.messaging.outgoing.chat-messages.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer # value.serializer omis - Quarkus génère automatiquement depuis Emitter<ChatMessageEvent>
# Topic: Reactions (likes, comments, shares) # Topic: Reactions (likes, comments, shares)
mp.messaging.outgoing.reactions.connector=smallrye-kafka mp.messaging.outgoing.reactions.connector=smallrye-kafka
mp.messaging.outgoing.reactions.topic=reactions mp.messaging.outgoing.reactions.topic=reactions
mp.messaging.outgoing.reactions.key.serializer=org.apache.kafka.common.serialization.StringSerializer mp.messaging.outgoing.reactions.key.serializer=org.apache.kafka.common.serialization.StringSerializer
mp.messaging.outgoing.reactions.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer # value.serializer omis - Quarkus génère automatiquement depuis Emitter<ReactionEvent>
# Topic: Presence Updates # Topic: Presence Updates
mp.messaging.outgoing.presence.connector=smallrye-kafka # NOTE: Configuration désactivée car non utilisée actuellement
mp.messaging.outgoing.presence.topic=presence.updates # PresenceService envoie directement via NotificationWebSocketNext.broadcastPresenceUpdate()
mp.messaging.outgoing.presence.key.serializer=org.apache.kafka.common.serialization.StringSerializer # Pour activer Kafka pour presence, décommentez ci-dessous et ajoutez un Emitter<PresenceEvent> dans PresenceService
mp.messaging.outgoing.presence.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer # mp.messaging.outgoing.presence.connector=smallrye-kafka
# mp.messaging.outgoing.presence.topic=presence.updates
# mp.messaging.outgoing.presence.key.serializer=org.apache.kafka.common.serialization.StringSerializer
# mp.messaging.outgoing.presence.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer
# ==================================================================== # ====================================================================
# Kafka Topics - Incoming (Kafka → WebSocket Bridge) # Kafka Topics - Incoming (Kafka → WebSocket Bridge)
# ==================================================================== # ====================================================================
# Consommer depuis Kafka et router vers WebSocket pour notifications # Consommer depuis Kafka et router vers WebSocket pour notifications
# Note: Quarkus génère automatiquement les deserializers Jackson basés sur le type générique Message<NotificationEvent>
mp.messaging.incoming.kafka-notifications.connector=smallrye-kafka mp.messaging.incoming.kafka-notifications.connector=smallrye-kafka
mp.messaging.incoming.kafka-notifications.topic=notifications mp.messaging.incoming.kafka-notifications.topic=notifications
mp.messaging.incoming.kafka-notifications.group.id=websocket-notifications-bridge mp.messaging.incoming.kafka-notifications.group.id=websocket-notifications-bridge
mp.messaging.incoming.kafka-notifications.key.deserializer=org.apache.kafka.common.serialization.StringDeserializer mp.messaging.incoming.kafka-notifications.key.deserializer=org.apache.kafka.common.serialization.StringDeserializer
mp.messaging.incoming.kafka-notifications.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer # value.deserializer omis - Quarkus génère automatiquement depuis Message<NotificationEvent>
mp.messaging.incoming.kafka-notifications.enable.auto.commit=true mp.messaging.incoming.kafka-notifications.enable.auto.commit=true
# Consommer depuis Kafka et router vers WebSocket pour chat # Consommer depuis Kafka et router vers WebSocket pour chat
# Note: Quarkus génère automatiquement les deserializers Jackson basés sur le type générique Message<ChatMessageEvent>
mp.messaging.incoming.kafka-chat.connector=smallrye-kafka mp.messaging.incoming.kafka-chat.connector=smallrye-kafka
mp.messaging.incoming.kafka-chat.topic=chat.messages mp.messaging.incoming.kafka-chat.topic=chat.messages
mp.messaging.incoming.kafka-chat.group.id=websocket-chat-bridge mp.messaging.incoming.kafka-chat.group.id=websocket-chat-bridge
mp.messaging.incoming.kafka-chat.key.deserializer=org.apache.kafka.common.serialization.StringDeserializer mp.messaging.incoming.kafka-chat.key.deserializer=org.apache.kafka.common.serialization.StringDeserializer
mp.messaging.incoming.kafka-chat.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer # value.deserializer omis - Quarkus génère automatiquement depuis Message<ChatMessageEvent>
mp.messaging.incoming.kafka-chat.enable.auto.commit=true mp.messaging.incoming.kafka-chat.enable.auto.commit=true
# Consommer depuis Kafka et router vers WebSocket pour réactions # Consommer depuis Kafka et router vers WebSocket pour réactions
# Note: Quarkus génère automatiquement les deserializers Jackson basés sur le type générique Message<ReactionEvent>
mp.messaging.incoming.kafka-reactions.connector=smallrye-kafka mp.messaging.incoming.kafka-reactions.connector=smallrye-kafka
mp.messaging.incoming.kafka-reactions.topic=reactions mp.messaging.incoming.kafka-reactions.topic=reactions
mp.messaging.incoming.kafka-reactions.group.id=websocket-reactions-bridge mp.messaging.incoming.kafka-reactions.group.id=websocket-reactions-bridge
mp.messaging.incoming.kafka-reactions.key.deserializer=org.apache.kafka.common.serialization.StringDeserializer mp.messaging.incoming.kafka-reactions.key.deserializer=org.apache.kafka.common.serialization.StringDeserializer
mp.messaging.incoming.kafka-reactions.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer # value.deserializer omis - Quarkus génère automatiquement depuis Message<ReactionEvent>
mp.messaging.incoming.kafka-reactions.enable.auto.commit=true mp.messaging.incoming.kafka-reactions.enable.auto.commit=true