From 95dc70d29b4cc7bc124a4a296d84c7850f7efc24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=8A=B9=EC=A7=84?= Date: Mon, 11 Mar 2024 16:34:09 +0900 Subject: [PATCH] =?UTF-8?q?[FEAT]=20rabbitmq=20deadletter=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/rabbitmq/RabbitMQConfig.java | 29 +++++++++++++---- .../domain/deadletter/DeadLetterConsumer.java | 32 +++++++++++++++++++ .../global/constant/RabbitMQConstant.java | 5 ++- .../src/main/resources/application-prod.yml | 2 ++ 4 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 backend/src/main/java/com/twtw/backend/domain/deadletter/DeadLetterConsumer.java diff --git a/backend/src/main/java/com/twtw/backend/config/rabbitmq/RabbitMQConfig.java b/backend/src/main/java/com/twtw/backend/config/rabbitmq/RabbitMQConfig.java index 4704bd5e..5cd84e44 100644 --- a/backend/src/main/java/com/twtw/backend/config/rabbitmq/RabbitMQConfig.java +++ b/backend/src/main/java/com/twtw/backend/config/rabbitmq/RabbitMQConfig.java @@ -3,13 +3,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.twtw.backend.global.constant.RabbitMQConstant; import com.twtw.backend.global.properties.RabbitMQProperties; - import lombok.RequiredArgsConstructor; - -import org.springframework.amqp.core.Binding; -import org.springframework.amqp.core.BindingBuilder; -import org.springframework.amqp.core.Queue; -import org.springframework.amqp.core.TopicExchange; +import org.springframework.amqp.core.*; import org.springframework.amqp.rabbit.annotation.EnableRabbit; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; @@ -61,6 +56,23 @@ public Binding notificationBinding() { .with(RabbitMQConstant.NOTIFICATION_ROUTING_KEY.getName()); } + @Bean + public Queue deadLetterQueue() { + return QueueBuilder.durable(RabbitMQConstant.DEAD_LETTER_QUEUE.getName()).build(); + } + + @Bean + public TopicExchange deadLetterExchange() { + return new TopicExchange(RabbitMQConstant.DEAD_LETTER_EXCHANGE.getName()); + } + + @Bean + public Binding deadLetterBinding() { + return BindingBuilder.bind(deadLetterQueue()) + .to(deadLetterExchange()) + .with(RabbitMQConstant.DEAD_LETTER_ROUTING_KEY.getName()); + } + @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory factory = new CachingConnectionFactory(); @@ -94,6 +106,11 @@ public RabbitAdmin rabbitAdmin(final ConnectionFactory connectionFactory) { rabbitAdmin.declareQueue(notificationQueue()); rabbitAdmin.declareExchange(notificationTopicExchange()); rabbitAdmin.declareBinding(notificationBinding()); + + rabbitAdmin.declareQueue(deadLetterQueue()); + rabbitAdmin.declareExchange(deadLetterExchange()); + rabbitAdmin.declareBinding(deadLetterBinding()); + return rabbitAdmin; } } diff --git a/backend/src/main/java/com/twtw/backend/domain/deadletter/DeadLetterConsumer.java b/backend/src/main/java/com/twtw/backend/domain/deadletter/DeadLetterConsumer.java new file mode 100644 index 00000000..5c64a875 --- /dev/null +++ b/backend/src/main/java/com/twtw/backend/domain/deadletter/DeadLetterConsumer.java @@ -0,0 +1,32 @@ +package com.twtw.backend.domain.deadletter; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClient; + +@Slf4j +@Component +public class DeadLetterConsumer { + + private final WebClient webClient; + private final String slackUrl; + + public DeadLetterConsumer(@Value("${slack.url}") final String slackUrl) { + this.webClient = WebClient.create("https://hooks.slack.com/services/"); + this.slackUrl = slackUrl; + } + + @RabbitListener(queues = "deadletter.queue") + public void handleDeadLetterMessage(final String message) { + log.error("Dead letter received: {}", message); + webClient.post() + .uri(slackUrl) + .bodyValue("{\"text\": \"Dead letter received: " + message + "\"}") + .retrieve() + .bodyToMono(String.class) + .doOnSuccess(s -> log.info("Slack message sent: {}", s)) + .subscribe(); + } +} diff --git a/backend/src/main/java/com/twtw/backend/global/constant/RabbitMQConstant.java b/backend/src/main/java/com/twtw/backend/global/constant/RabbitMQConstant.java index 6c9dbc4c..a072e6a3 100644 --- a/backend/src/main/java/com/twtw/backend/global/constant/RabbitMQConstant.java +++ b/backend/src/main/java/com/twtw/backend/global/constant/RabbitMQConstant.java @@ -12,7 +12,10 @@ public enum RabbitMQConstant { LOCATION_ROUTING_KEY_PREFIX("location."), NOTIFICATION_QUEUE("notification.queue"), NOTIFICATION_EXCHANGE("notification"), - NOTIFICATION_ROUTING_KEY("notification"); + NOTIFICATION_ROUTING_KEY("notification"), + DEAD_LETTER_QUEUE("deadletter.queue"), + DEAD_LETTER_EXCHANGE("deadletter"), + DEAD_LETTER_ROUTING_KEY("deadletter"); private final String name; } diff --git a/backend/src/main/resources/application-prod.yml b/backend/src/main/resources/application-prod.yml index c24918cb..dc6ecf6e 100644 --- a/backend/src/main/resources/application-prod.yml +++ b/backend/src/main/resources/application-prod.yml @@ -83,3 +83,5 @@ tmap: url: ${TMAP_URL} firebase: location: ${FIREBASE_LOCATION} +slack: + url: ${SLACK_URL} \ No newline at end of file