diff --git a/src/main/java/com/lions/dev/websocket/bridge/ChatKafkaBridge.java b/src/main/java/com/lions/dev/websocket/bridge/ChatKafkaBridge.java index be16a52..dc60826 100644 --- a/src/main/java/com/lions/dev/websocket/bridge/ChatKafkaBridge.java +++ b/src/main/java/com/lions/dev/websocket/bridge/ChatKafkaBridge.java @@ -9,6 +9,7 @@ import org.eclipse.microprofile.reactive.messaging.Message; import java.util.UUID; import java.util.Map; +import java.util.concurrent.CompletionStage; /** * 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. + * + * @param message Message Kafka contenant un ChatMessageEvent + * @return CompletionStage pour gérer l'ack/nack asynchrone */ @Incoming("kafka-chat") - public void processChatMessage(Message message) { + public CompletionStage processChatMessage(Message message) { try { ChatMessageEvent event = message.getPayload(); @@ -38,17 +42,17 @@ public class ChatKafkaBridge { // Envoyer via WebSocket au destinataire ChatWebSocketNext.sendMessageToUser(recipientId, wsMessage); - // Acknowledger le message Kafka - message.ack(); - Log.debug("[CHAT-BRIDGE] Message routé vers WebSocket pour: " + event.getRecipientId()); + // Acknowledger le message Kafka + return message.ack(); + } catch (IllegalArgumentException e) { Log.error("[CHAT-BRIDGE] UUID invalide dans l'événement", e); - message.nack(e); + return message.nack(e); } catch (Exception e) { Log.error("[CHAT-BRIDGE] Erreur traitement événement", e); - message.nack(e); + return message.nack(e); } } diff --git a/src/main/java/com/lions/dev/websocket/bridge/NotificationKafkaBridge.java b/src/main/java/com/lions/dev/websocket/bridge/NotificationKafkaBridge.java index 77e07ff..92da2a5 100644 --- a/src/main/java/com/lions/dev/websocket/bridge/NotificationKafkaBridge.java +++ b/src/main/java/com/lions/dev/websocket/bridge/NotificationKafkaBridge.java @@ -8,6 +8,8 @@ import org.eclipse.microprofile.reactive.messaging.Incoming; import org.eclipse.microprofile.reactive.messaging.Message; 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. @@ -27,9 +29,10 @@ public class NotificationKafkaBridge { * Consomme les événements depuis Kafka et les route vers WebSocket. * * @param message Message Kafka contenant un NotificationEvent + * @return CompletionStage pour gérer l'ack/nack asynchrone */ @Incoming("kafka-notifications") - public void processNotification(Message message) { + public CompletionStage processNotification(Message message) { try { NotificationEvent event = message.getPayload(); @@ -44,17 +47,17 @@ public class NotificationKafkaBridge { // Envoyer via WebSocket NotificationWebSocketNext.sendToUser(userId, wsMessage); - // Acknowledger le message Kafka - message.ack(); - Log.debug("[KAFKA-BRIDGE] Notification routée vers WebSocket pour: " + event.getUserId()); + // Acknowledger le message Kafka + return message.ack(); + } catch (IllegalArgumentException e) { Log.error("[KAFKA-BRIDGE] UUID invalide dans l'événement", e); - message.nack(e); + return message.nack(e); } catch (Exception e) { Log.error("[KAFKA-BRIDGE] Erreur traitement événement", e); - message.nack(e); + return message.nack(e); } } diff --git a/src/main/java/com/lions/dev/websocket/bridge/ReactionKafkaBridge.java b/src/main/java/com/lions/dev/websocket/bridge/ReactionKafkaBridge.java index 89e4af1..6d2ae7d 100644 --- a/src/main/java/com/lions/dev/websocket/bridge/ReactionKafkaBridge.java +++ b/src/main/java/com/lions/dev/websocket/bridge/ReactionKafkaBridge.java @@ -8,6 +8,7 @@ import org.eclipse.microprofile.reactive.messaging.Incoming; import org.eclipse.microprofile.reactive.messaging.Message; import java.util.UUID; +import java.util.concurrent.CompletionStage; /** * 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. + * + * @param message Message Kafka contenant un ReactionEvent + * @return CompletionStage pour gérer l'ack/nack asynchrone */ @Incoming("kafka-reactions") - public void processReaction(Message message) { + public CompletionStage processReaction(Message message) { try { ReactionEvent event = message.getPayload(); @@ -50,14 +54,14 @@ public class ReactionKafkaBridge { } // Acknowledger le message Kafka - message.ack(); + return message.ack(); } catch (IllegalArgumentException e) { Log.error("[REACTION-BRIDGE] UUID invalide dans l'événement", e); - message.nack(e); + return message.nack(e); } catch (Exception e) { Log.error("[REACTION-BRIDGE] Erreur traitement événement", e); - message.nack(e); + return message.nack(e); } } diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties deleted file mode 100644 index d903256..0000000 --- a/src/main/resources/application-prod.properties +++ /dev/null @@ -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 diff --git a/src/main/resources/application-production.properties b/src/main/resources/application-production.properties index 36bc35b..38ec36e 100644 --- a/src/main/resources/application-production.properties +++ b/src/main/resources/application-production.properties @@ -3,9 +3,6 @@ # ==================================================================== # Ce fichier est automatiquement chargé avec: java -jar app.jar # 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 @@ -58,7 +55,8 @@ quarkus.log.category."io.quarkus".level=INFO # ==================================================================== # 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) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3c5e5a5..ecf1c83 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -5,6 +5,10 @@ # Les configurations spécifiques sont dans : # - application-dev.properties (développement) # - 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) @@ -19,6 +23,22 @@ quarkus.smallrye-openapi.path=/openapi quarkus.http.host=0.0.0.0 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) # ==================================================================== @@ -40,53 +60,60 @@ kafka.bootstrap.servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092} # ==================================================================== # Kafka Topics - Outgoing (Services → Kafka) # ==================================================================== +# Note: Quarkus génère automatiquement les serializers Jackson basés sur le type Emitter # Topic: Notifications mp.messaging.outgoing.notifications.connector=smallrye-kafka mp.messaging.outgoing.notifications.topic=notifications 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 # Topic: Chat Messages mp.messaging.outgoing.chat-messages.connector=smallrye-kafka 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.value.serializer=io.quarkus.kafka.client.serialization.JsonbSerializer +# value.serializer omis - Quarkus génère automatiquement depuis Emitter # Topic: Reactions (likes, comments, shares) mp.messaging.outgoing.reactions.connector=smallrye-kafka mp.messaging.outgoing.reactions.topic=reactions 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 # Topic: Presence Updates -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 +# NOTE: Configuration désactivée car non utilisée actuellement +# PresenceService envoie directement via NotificationWebSocketNext.broadcastPresenceUpdate() +# Pour activer Kafka pour presence, décommentez ci-dessous et ajoutez un Emitter dans PresenceService +# 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) # ==================================================================== # 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 mp.messaging.incoming.kafka-notifications.connector=smallrye-kafka mp.messaging.incoming.kafka-notifications.topic=notifications 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.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer +# value.deserializer omis - Quarkus génère automatiquement depuis Message mp.messaging.incoming.kafka-notifications.enable.auto.commit=true # 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 mp.messaging.incoming.kafka-chat.connector=smallrye-kafka mp.messaging.incoming.kafka-chat.topic=chat.messages 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.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer +# value.deserializer omis - Quarkus génère automatiquement depuis Message mp.messaging.incoming.kafka-chat.enable.auto.commit=true # 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 mp.messaging.incoming.kafka-reactions.connector=smallrye-kafka mp.messaging.incoming.kafka-reactions.topic=reactions 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.value.deserializer=io.quarkus.kafka.client.serialization.JsonbDeserializer +# value.deserializer omis - Quarkus génère automatiquement depuis Message mp.messaging.incoming.kafka-reactions.enable.auto.commit=true