Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BG-318]: RMQ notification 브로커 만들기 (2h / 2h) #62

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions infra/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ plugins {
group = "com.backgu.amaker"
version = "0.0.1-SNAPSHOT"

kapt {
correctErrorTypes = true
}

Comment on lines +11 to +14
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

뭐 때매 발생했어?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

으음... 사실 잘 모르겠는데 그냥 .class 파일 번역한 부분에서 kapt 에서 코드를 찾을 수 없다 뭐 그런식으로 나왔는데 그냥 검색해서 대충 해결한거라ㅎㅎ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

repositories {
mavenCentral()
}
Expand All @@ -31,6 +35,9 @@ dependencies {
implementation("com.querydsl:querydsl-apt:5.0.0:jakarta")
implementation("jakarta.persistence:jakarta.persistence-api")
implementation("jakarta.annotation:jakarta.annotation-api")
implementation("org.springframework.boot:spring-boot-starter-amqp")

testImplementation("org.springframework.amqp:spring-rabbit-test")
kapt("com.querydsl:querydsl-apt:5.0.0:jakarta")
kapt("org.springframework.boot:spring-boot-configuration-processor")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.backgu.amaker.infra.notification.rmq.config

import com.backgu.amaker.infra.notification.rmq.serivce.RMQEventPublisher
import com.backgu.amaker.infra.rmq.config.RMQConfig
import org.springframework.amqp.core.AcknowledgeMode
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory
import org.springframework.amqp.rabbit.connection.ConnectionFactory
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter
import org.springframework.context.ApplicationEventPublisher
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import

@Configuration
@Import(RMQConfig::class)
class NotificationRMQEventPublisherConfig(
private val applicationEventPublisher: ApplicationEventPublisher,
private val jackson2JsonMessageConverter: Jackson2JsonMessageConverter,
) {
@Bean
fun rabbitListenerContainerFactory(connectionFactory: ConnectionFactory): RabbitListenerContainerFactory<*> {
val factory = SimpleRabbitListenerContainerFactory()
factory.setConnectionFactory(connectionFactory)
factory.setMessageConverter(jackson2JsonMessageConverter)
factory.setAcknowledgeMode(AcknowledgeMode.MANUAL)
return factory
}

@Bean
fun notificationRMQEventPublisher(): RMQEventPublisher = RMQEventPublisher(applicationEventPublisher)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.backgu.amaker.infra.notification.rmq.config

import com.backgu.amaker.application.notification.service.NotificationEventService
import com.backgu.amaker.infra.notification.rmq.serivce.NotificationRMQEventService
import com.backgu.amaker.infra.rmq.config.RMQConfig
import org.springframework.amqp.rabbit.connection.ConnectionFactory
import org.springframework.amqp.rabbit.core.RabbitTemplate
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import

@Configuration
@Import(RMQConfig::class)
class NotificationRMQProducerConfig(
private val jackson2JsonMessageConverter: Jackson2JsonMessageConverter,
) {
@Bean
fun rabbitTemplate(connectionFactory: ConnectionFactory): RabbitTemplate {
val rabbitTemplate = RabbitTemplate(connectionFactory)
rabbitTemplate.messageConverter = jackson2JsonMessageConverter
return rabbitTemplate
}

@Bean
fun notificationRMQEventService(rabbitTemplate: RabbitTemplate): NotificationEventService = NotificationRMQEventService(rabbitTemplate)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.backgu.amaker.infra.notification.rmq.serivce

import com.backgu.amaker.application.notification.event.NotificationEvent
import com.backgu.amaker.application.notification.service.NotificationEventService
import com.backgu.amaker.infra.rmq.config.RMQConfig
import org.springframework.amqp.rabbit.core.RabbitTemplate

class NotificationRMQEventService(
private val rabbitTemplate: RabbitTemplate,
) : NotificationEventService {
override fun publishNotificationEvent(notificationEvent: NotificationEvent) {
rabbitTemplate.convertAndSend(RMQConfig.NOTIFICATION_QUEUE, notificationEvent)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.backgu.amaker.infra.notification.rmq.serivce

import com.backgu.amaker.application.notification.event.NotificationEventWithCallback
import com.backgu.amaker.application.notification.mail.event.EmailEvent
import com.backgu.amaker.infra.rmq.config.RMQConfig
import com.rabbitmq.client.Channel
import org.springframework.amqp.rabbit.annotation.RabbitListener
import org.springframework.amqp.support.AmqpHeaders
import org.springframework.context.ApplicationEventPublisher
import org.springframework.messaging.handler.annotation.Headers

class RMQEventPublisher(
private val applicationEventPublisher: ApplicationEventPublisher,
) {
@RabbitListener(queues = [RMQConfig.NOTIFICATION_QUEUE])
fun publish(
notificationEvent: EmailEvent,
channel: Channel,
@Headers headers: Map<String, Any>,
) {
val deliveryTag = headers[AmqpHeaders.DELIVERY_TAG] as Long

applicationEventPublisher.publishEvent(
object : NotificationEventWithCallback {
override val notificationEvent = notificationEvent

override fun postHandle() {
channel.basicAck(deliveryTag, false)
}

override fun onFail(exception: Exception) {
channel.basicNack(deliveryTag, false, true)
}
},
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.backgu.amaker.infra.rmq.config

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.rabbit.connection.CachingConnectionFactory
import org.springframework.amqp.rabbit.connection.ConnectionFactory
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
@ConfigurationProperties(prefix = "spring.rabbitmq")
class RMQConfig {
companion object {
const val NOTIFICATION_QUEUE = "notification"
const val NOTIFICATION_EXCHANGE = "notification"
const val NOTIFICATION_ROUTING_KEY = "notification"
}

lateinit var host: String
var port: Int = 0
lateinit var username: String
lateinit var password: String

@Bean
fun jackson2JsonMessageConverter(): Jackson2JsonMessageConverter = Jackson2JsonMessageConverter()

@Bean
fun queue(): Queue = Queue(RMQConfig.NOTIFICATION_QUEUE, false)

@Bean
fun topicExchange(): TopicExchange = TopicExchange(RMQConfig.NOTIFICATION_EXCHANGE)

@Bean
fun binding(): Binding = BindingBuilder.bind(queue()).to(topicExchange()).with(RMQConfig.NOTIFICATION_ROUTING_KEY)

@Bean
fun connectionFactory(): ConnectionFactory {
val connectionFactory = CachingConnectionFactory(host, port)
connectionFactory.username = username
connectionFactory.setPassword(password)
return connectionFactory
}
}
1 change: 0 additions & 1 deletion notification/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ dependencies {
implementation(project(":domain"))
implementation(project(":infra"))
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-web")
testImplementation(kotlin("test"))
}

Expand Down
Loading