From ae8492f6df1f40c62285be4bbf95774bde234449 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Fri, 5 Jan 2024 02:52:10 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20=EB=B2=88=EC=97=AD=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=20=EA=B0=9D=EC=B2=B4=EC=97=90=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=ED=8F=AC=ED=95=A8=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD,=20=EB=B2=88?= =?UTF-8?q?=EC=97=AD=20=EC=84=B1=EA=B3=B5=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v1/translation/dto/TranslationRequest.kt | 2 +- .../NewsAppendContentEventListener.kt | 9 ++--- .../application/dto/NewsAppendContentEvent.kt | 8 +++-- .../application/TranslationCommandService.kt | 32 +++++++++++++---- ...r.kt => TranslationResultEventListener.kt} | 18 +++++++--- .../application/TranslatorClient.kt | 26 ++++++++++++++ .../TranslatorClients.kt | 3 +- .../application/dto/TranslationCommand.kt | 12 ------- .../application/dto/TranslatorFailureEvent.kt | 8 ----- .../config/TranslatorClientConfig.kt | 4 +-- .../sc/translation/domain/TranslatorClient.kt | 12 ------- .../infra/DeepLTranslatorClient.kt | 35 +++++++++++-------- .../TranslationCommandServiceTest.kt | 26 ++++++++------ .../infra/DeepLTranslatorClientTest.kt | 21 +++++++---- 14 files changed, 130 insertions(+), 86 deletions(-) rename src/main/kotlin/kr/galaxyhub/sc/translation/application/{TranslationAppendContentEventListener.kt => TranslationResultEventListener.kt} (80%) create mode 100644 src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslatorClient.kt rename src/main/kotlin/kr/galaxyhub/sc/translation/{domain => application}/TranslatorClients.kt (89%) delete mode 100644 src/main/kotlin/kr/galaxyhub/sc/translation/application/dto/TranslationCommand.kt delete mode 100644 src/main/kotlin/kr/galaxyhub/sc/translation/application/dto/TranslatorFailureEvent.kt delete mode 100644 src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslatorClient.kt diff --git a/src/main/kotlin/kr/galaxyhub/sc/api/v1/translation/dto/TranslationRequest.kt b/src/main/kotlin/kr/galaxyhub/sc/api/v1/translation/dto/TranslationRequest.kt index 1db4965..770a54f 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/api/v1/translation/dto/TranslationRequest.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/api/v1/translation/dto/TranslationRequest.kt @@ -2,7 +2,7 @@ package kr.galaxyhub.sc.api.v1.translation.dto import java.util.UUID import kr.galaxyhub.sc.news.domain.Language -import kr.galaxyhub.sc.translation.application.dto.TranslationCommand +import kr.galaxyhub.sc.translation.application.TranslationCommand import kr.galaxyhub.sc.translation.domain.TranslatorProvider data class TranslationRequest( diff --git a/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt b/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt index 6bb6c24..aafcc52 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt @@ -2,6 +2,7 @@ package kr.galaxyhub.sc.news.application import io.github.oshai.kotlinlogging.KotlinLogging import kr.galaxyhub.sc.news.application.dto.NewsAppendContentEvent +import kr.galaxyhub.sc.news.domain.Content import kr.galaxyhub.sc.news.domain.NewsRepository import kr.galaxyhub.sc.news.domain.getOrThrow import org.springframework.context.event.EventListener @@ -21,14 +22,14 @@ class NewsAppendContentEventListener( ) { @EventListener - fun appendContent(event: NewsAppendContentEvent) { + fun newsAppendContentEventHandler(event: NewsAppendContentEvent) { + val (newsId, newsInformation, content, language) = event runCatching { - newsRepository.getOrThrow(event.newsId) + newsRepository.getOrThrow(newsId) }.onSuccess { - it.addContent(event.content) + it.addContent(Content(newsId, newsInformation, language, content)) }.onFailure { log.error { "뉴스에 컨텐츠를 추가하는 중 예외가 발생했습니다. ${it.message}" } } } } - diff --git a/src/main/kotlin/kr/galaxyhub/sc/news/application/dto/NewsAppendContentEvent.kt b/src/main/kotlin/kr/galaxyhub/sc/news/application/dto/NewsAppendContentEvent.kt index b73f332..993a6bf 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/news/application/dto/NewsAppendContentEvent.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/news/application/dto/NewsAppendContentEvent.kt @@ -1,10 +1,12 @@ package kr.galaxyhub.sc.news.application.dto import java.util.UUID -import kr.galaxyhub.sc.news.domain.Content +import kr.galaxyhub.sc.news.domain.Language +import kr.galaxyhub.sc.news.domain.NewsInformation data class NewsAppendContentEvent( val newsId: UUID, - val translateProgressionId: UUID, - val content: Content + val newsInformation: NewsInformation, + val content: String, + val language: Language ) diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandService.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandService.kt index 3528050..21c7974 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandService.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandService.kt @@ -4,13 +4,13 @@ import io.github.oshai.kotlinlogging.KotlinLogging import java.util.UUID import kr.galaxyhub.sc.common.support.validate import kr.galaxyhub.sc.news.application.dto.NewsAppendContentEvent +import kr.galaxyhub.sc.news.domain.Content +import kr.galaxyhub.sc.news.domain.Language import kr.galaxyhub.sc.news.domain.NewsRepository import kr.galaxyhub.sc.news.domain.getFetchByIdAndLanguage -import kr.galaxyhub.sc.translation.application.dto.TranslationCommand -import kr.galaxyhub.sc.translation.application.dto.TranslatorFailureEvent import kr.galaxyhub.sc.translation.domain.TranslateProgression import kr.galaxyhub.sc.translation.domain.TranslationProgressionRepository -import kr.galaxyhub.sc.translation.domain.TranslatorClients +import kr.galaxyhub.sc.translation.domain.TranslatorProvider import org.springframework.context.ApplicationEventPublisher import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -31,18 +31,38 @@ class TranslationCommandService( val news = newsRepository.getFetchByIdAndLanguage(newsId, sourceLanguage) validate(news.isSupportLanguage(targetLanguage)) { "이미 뉴스에 번역된 컨텐츠가 존재합니다. targetLanguage=$targetLanguage" } val content = news.getContentByLanguage(sourceLanguage) + val translateProgression = TranslateProgression(newsId, sourceLanguage, targetLanguage, translatorProvider) translationProgressionRepository.save(translateProgression) + val translatorClient = translatorClients.getClient(translatorProvider) - translatorClient.requestTranslate(content, targetLanguage) + translatorClient.requestTranslate(content.toRequest(targetLanguage)) .doOnError { log.info { "뉴스 번역 요청이 실패하였습니다. newsId=${newsId}, translateProgressionId=${translateProgression.id} cause=${it.message}" } - eventPublisher.publishEvent(TranslatorFailureEvent(translateProgression.id, it.message)) + eventPublisher.publishEvent(TranslationFailureEvent(translateProgression.id, it.message)) } .subscribe { log.info { "뉴스 번역 요청이 완료되었습니다. newsId=${newsId}, translateProgressionId=${translateProgression.id}" } - eventPublisher.publishEvent(NewsAppendContentEvent(newsId, translateProgression.id, it)) + eventPublisher.publishEvent(NewsAppendContentEvent(newsId, it.newsInformation, it.content, it.language)) + eventPublisher.publishEvent(TranslationSuccessEvent(translateProgression.id)) } return translateProgression.id } + + private fun Content.toRequest(targetLanguage: Language): TranslatorClientRequest { + return TranslatorClientRequest( + newsInformation = newsInformation, + content = content, + sourceLanguage = language, + targetLanguage = targetLanguage + ) + } } + +data class TranslationCommand( + val newsId: UUID, + val sourceLanguage: Language, + val targetLanguage: Language, + val translatorProvider: TranslatorProvider, +) + diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationAppendContentEventListener.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationResultEventListener.kt similarity index 80% rename from src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationAppendContentEventListener.kt rename to src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationResultEventListener.kt index 691b3cc..77c565a 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationAppendContentEventListener.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationResultEventListener.kt @@ -1,8 +1,7 @@ package kr.galaxyhub.sc.translation.application import io.github.oshai.kotlinlogging.KotlinLogging -import kr.galaxyhub.sc.news.application.dto.NewsAppendContentEvent -import kr.galaxyhub.sc.translation.application.dto.TranslatorFailureEvent +import java.util.UUID import kr.galaxyhub.sc.translation.domain.TranslationProgressionRepository import kr.galaxyhub.sc.translation.domain.getOrThrow import org.springframework.context.event.EventListener @@ -19,12 +18,12 @@ private val log = KotlinLogging.logger {} */ @Component @Transactional -class TranslationAppendContentEventListener( +class TranslationResultEventListener( private val translationProgressionRepository: TranslationProgressionRepository ) { @EventListener - fun changeTranslationProgressionComplete(event: NewsAppendContentEvent) { + fun translatorSuccessEventHandler(event: TranslationSuccessEvent) { runCatching { translationProgressionRepository.getOrThrow(event.translateProgressionId) }.onSuccess { @@ -35,7 +34,7 @@ class TranslationAppendContentEventListener( } @EventListener - fun changeTranslationProgressionFailure(event: TranslatorFailureEvent) { + fun translatorFailureEventHandler(event: TranslationFailureEvent) { runCatching { translationProgressionRepository.getOrThrow(event.translateProgressionId) }.onSuccess { @@ -46,3 +45,12 @@ class TranslationAppendContentEventListener( } } +data class TranslationSuccessEvent( + val translateProgressionId: UUID, +) + +data class TranslationFailureEvent( + val translateProgressionId: UUID, + val message: String? +) + diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslatorClient.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslatorClient.kt new file mode 100644 index 0000000..31b0b17 --- /dev/null +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslatorClient.kt @@ -0,0 +1,26 @@ +package kr.galaxyhub.sc.translation.application + +import kr.galaxyhub.sc.news.domain.Language +import kr.galaxyhub.sc.news.domain.NewsInformation +import kr.galaxyhub.sc.translation.domain.TranslatorProvider +import reactor.core.publisher.Mono + +interface TranslatorClient { + + fun requestTranslate(request: TranslatorClientRequest): Mono + + fun getProvider(): TranslatorProvider +} + +data class TranslatorClientRequest( + val newsInformation: NewsInformation, + val content: String, + val sourceLanguage: Language, + val targetLanguage: Language, +) + +data class TranslatorClientResponse( + val newsInformation: NewsInformation, + val content: String, + val language: Language +) diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslatorClients.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslatorClients.kt similarity index 89% rename from src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslatorClients.kt rename to src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslatorClients.kt index b8ffb10..a6dd673 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslatorClients.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslatorClients.kt @@ -1,7 +1,8 @@ -package kr.galaxyhub.sc.translation.domain +package kr.galaxyhub.sc.translation.application import java.util.EnumMap import kr.galaxyhub.sc.common.exception.BadRequestException +import kr.galaxyhub.sc.translation.domain.TranslatorProvider class TranslatorClients( private val translatorClients: Map, diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/dto/TranslationCommand.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/dto/TranslationCommand.kt deleted file mode 100644 index 9010b40..0000000 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/application/dto/TranslationCommand.kt +++ /dev/null @@ -1,12 +0,0 @@ -package kr.galaxyhub.sc.translation.application.dto - -import java.util.UUID -import kr.galaxyhub.sc.news.domain.Language -import kr.galaxyhub.sc.translation.domain.TranslatorProvider - -data class TranslationCommand( - val newsId: UUID, - val sourceLanguage: Language, - val targetLanguage: Language, - val translatorProvider: TranslatorProvider, -) diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/dto/TranslatorFailureEvent.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/dto/TranslatorFailureEvent.kt deleted file mode 100644 index 41e547f..0000000 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/application/dto/TranslatorFailureEvent.kt +++ /dev/null @@ -1,8 +0,0 @@ -package kr.galaxyhub.sc.translation.application.dto - -import java.util.UUID - -data class TranslatorFailureEvent( - val translateProgressionId: UUID, - val message: String? -) diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/config/TranslatorClientConfig.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/config/TranslatorClientConfig.kt index 68bcda6..49c01a4 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/config/TranslatorClientConfig.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/config/TranslatorClientConfig.kt @@ -1,8 +1,8 @@ package kr.galaxyhub.sc.translation.config import java.time.Duration -import kr.galaxyhub.sc.translation.domain.TranslatorClient -import kr.galaxyhub.sc.translation.domain.TranslatorClients +import kr.galaxyhub.sc.translation.application.TranslatorClient +import kr.galaxyhub.sc.translation.application.TranslatorClients import kr.galaxyhub.sc.translation.infra.DeepLTranslatorClient import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslatorClient.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslatorClient.kt deleted file mode 100644 index 2270ab9..0000000 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslatorClient.kt +++ /dev/null @@ -1,12 +0,0 @@ -package kr.galaxyhub.sc.translation.domain - -import kr.galaxyhub.sc.news.domain.Content -import kr.galaxyhub.sc.news.domain.Language -import reactor.core.publisher.Mono - -interface TranslatorClient { - - fun requestTranslate(content: Content, targetLanguage: Language): Mono - - fun getProvider(): TranslatorProvider -} diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/infra/DeepLTranslatorClient.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/infra/DeepLTranslatorClient.kt index d47ece0..d285bcb 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/infra/DeepLTranslatorClient.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/infra/DeepLTranslatorClient.kt @@ -4,14 +4,14 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming import io.github.oshai.kotlinlogging.KotlinLogging import java.time.Duration -import java.util.UUID import kr.galaxyhub.sc.common.exception.BadRequestException import kr.galaxyhub.sc.common.exception.InternalServerError import kr.galaxyhub.sc.common.support.handleConnectError -import kr.galaxyhub.sc.news.domain.Content import kr.galaxyhub.sc.news.domain.Language import kr.galaxyhub.sc.news.domain.NewsInformation -import kr.galaxyhub.sc.translation.domain.TranslatorClient +import kr.galaxyhub.sc.translation.application.TranslatorClient +import kr.galaxyhub.sc.translation.application.TranslatorClientRequest +import kr.galaxyhub.sc.translation.application.TranslatorClientResponse import kr.galaxyhub.sc.translation.domain.TranslatorProvider import org.springframework.http.HttpStatus import org.springframework.web.reactive.function.client.ClientResponse @@ -26,10 +26,17 @@ class DeepLTranslatorClient( private val timeoutDuration: Duration, ) : TranslatorClient { - override fun requestTranslate(content: Content, targetLanguage: Language): Mono { + override fun requestTranslate(request: TranslatorClientRequest): Mono { + val (newsInformation, content, sourceLanguage, targetLanguage) = request return webClient.post() .uri("/v2/translate") - .bodyValue(DeepLRequest(content.language.shortName, targetLanguage.shortName, content.toText())) + .bodyValue( + DeepLRequest( + sourceLang = sourceLanguage.shortName, + targetLang = targetLanguage.shortName, + text = toText(newsInformation, content) + ) + ) .retrieve() .onStatus({ it.isError }) { log.info { "DeepL ErrorResponse=${it.bodyToMono().block()}" } // 에러 응답 확인용. 추후 불필요하면 삭제 @@ -41,7 +48,7 @@ class DeepLTranslatorClient( log.info { "DeepL 서버의 응답 시간이 초과되었습니다." } InternalServerError("DeepL 서버의 응답 시간이 초과되었습니다.") }) - .map { it.toContent(content.newsId, targetLanguage) } + .map { it.toResponse(targetLanguage) } } /** @@ -70,7 +77,7 @@ class DeepLTranslatorClient( return TranslatorProvider.DEEPL } - private fun Content.toText(): List { + private fun toText(newsInformation: NewsInformation, content: String): List { val text = mutableListOf() text.add(newsInformation.title) text.add(newsInformation.excerpt ?: "") @@ -90,13 +97,11 @@ internal data class DeepLResponse( val translations: List, ) { - fun toContent(newsId: UUID, language: Language): Content { - val newsInformation = toNewsInformation() - return Content( - newsId = newsId, - newsInformation = newsInformation, - language = language, - content = toContentString() + fun toResponse(language: Language): TranslatorClientResponse { + return TranslatorClientResponse( + newsInformation = toNewsInformation(), + content = toContent(), + language = language ) } @@ -105,7 +110,7 @@ internal data class DeepLResponse( .let { NewsInformation(it[0].text, it[1].text) } } - private fun toContentString(): String { + private fun toContent(): String { return translations.subList(2, translations.size) .joinToString(System.lineSeparator()) { it.text } } diff --git a/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandServiceTest.kt b/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandServiceTest.kt index 8c6d772..73ffd3f 100644 --- a/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandServiceTest.kt +++ b/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandServiceTest.kt @@ -13,13 +13,10 @@ import kr.galaxyhub.sc.common.exception.NotFoundException import kr.galaxyhub.sc.news.application.dto.NewsAppendContentEvent import kr.galaxyhub.sc.news.domain.Language import kr.galaxyhub.sc.news.domain.MemoryNewsRepository +import kr.galaxyhub.sc.news.domain.NewsInformation import kr.galaxyhub.sc.news.fixture.ContentFixture import kr.galaxyhub.sc.news.fixture.NewsFixture -import kr.galaxyhub.sc.translation.application.dto.TranslationCommand -import kr.galaxyhub.sc.translation.application.dto.TranslatorFailureEvent import kr.galaxyhub.sc.translation.domain.MemoryTranslationProgressionRepository -import kr.galaxyhub.sc.translation.domain.TranslatorClient -import kr.galaxyhub.sc.translation.domain.TranslatorClients import kr.galaxyhub.sc.translation.domain.TranslatorProvider import kr.galaxyhub.sc.translation.domain.getOrThrow import org.springframework.context.ApplicationEventPublisher @@ -78,10 +75,10 @@ class TranslationCommandServiceTest : DescribeSpec({ news.addContent(ContentFixture.create(newsId = news.id, language = Language.ENGLISH)) newsRepository.save(news) val command = TranslationCommand(news.id, Language.ENGLISH, Language.KOREAN, TranslatorProvider.LOCAL) - every { translatorClient.requestTranslate(any(), any()) } returns Mono.fromSupplier { + every { translatorClient.requestTranslate(any()) } returns Mono.fromSupplier { throw IllegalArgumentException() } - every { eventPublisher.publishEvent(ofType()) } returns Unit + every { eventPublisher.publishEvent(ofType()) } returns Unit val translateProgressionId = translationCommandService.translate(command) @@ -92,12 +89,16 @@ class TranslationCommandServiceTest : DescribeSpec({ } it("TranslatorFailureEvent 이벤트가 발행된다.") { - verify { eventPublisher.publishEvent(ofType()) } + verify { eventPublisher.publishEvent(ofType()) } } it("NewsAppendContentEvent 이벤트는 발행되지 않는다.") { verify(exactly = 0) { eventPublisher.publishEvent(ofType()) } } + + it("TranslationSuccessEvent 이벤트는 발행되지 않는다.") { + verify(exactly = 0) { eventPublisher.publishEvent(ofType()) } + } } context("유효한 요청이 전달되면") { @@ -105,9 +106,10 @@ class TranslationCommandServiceTest : DescribeSpec({ news.addContent(ContentFixture.create(newsId = news.id, language = Language.ENGLISH)) newsRepository.save(news) val command = TranslationCommand(news.id, Language.ENGLISH, Language.KOREAN, TranslatorProvider.LOCAL) - val translatedContent = ContentFixture.create(newsId = news.id, language = Language.KOREAN) - every { translatorClient.requestTranslate(any(), any()) } returns Mono.just(translatedContent) + val translatorClientResponse = TranslatorClientResponse(NewsInformation("제목", "발췌"), "내용", Language.KOREAN) + every { translatorClient.requestTranslate(any()) } returns Mono.just(translatorClientResponse) every { eventPublisher.publishEvent(ofType()) } returns Unit + every { eventPublisher.publishEvent(ofType()) } returns Unit val translateProgressionId = translationCommandService.translate(command) @@ -121,8 +123,12 @@ class TranslationCommandServiceTest : DescribeSpec({ verify { eventPublisher.publishEvent(ofType()) } } + it("TranslationSuccessEvent 이벤트가 발행된다.") { + verify { eventPublisher.publishEvent(ofType()) } + } + it("TranslatorFailureEvent 이벤트는 발행되지 않는다.") { - verify(exactly = 0) { eventPublisher.publishEvent(ofType()) } + verify(exactly = 0) { eventPublisher.publishEvent(ofType()) } } } } diff --git a/src/test/kotlin/kr/galaxyhub/sc/translation/infra/DeepLTranslatorClientTest.kt b/src/test/kotlin/kr/galaxyhub/sc/translation/infra/DeepLTranslatorClientTest.kt index a388999..e9efc26 100644 --- a/src/test/kotlin/kr/galaxyhub/sc/translation/infra/DeepLTranslatorClientTest.kt +++ b/src/test/kotlin/kr/galaxyhub/sc/translation/infra/DeepLTranslatorClientTest.kt @@ -13,7 +13,7 @@ import kr.galaxyhub.sc.common.exception.InternalServerError import kr.galaxyhub.sc.common.support.enqueue import kr.galaxyhub.sc.news.domain.Language import kr.galaxyhub.sc.news.domain.NewsInformation -import kr.galaxyhub.sc.news.fixture.ContentFixture +import kr.galaxyhub.sc.translation.application.TranslatorClientRequest import okhttp3.mockwebserver.MockWebServer import org.springframework.web.reactive.function.client.WebClient @@ -57,7 +57,7 @@ class DeepLTranslatorClientTest : DescribeSpec({ body(response) } - val expect = deepLTranslatorClient.requestTranslate(ContentFixture.create(), Language.KOREAN).block()!! + val expect = deepLTranslatorClient.requestTranslate(translationRequest()).block()!! it("번역된 응답이 반환된다.") { assertSoftly { @@ -72,7 +72,7 @@ class DeepLTranslatorClientTest : DescribeSpec({ statusCode(429) } - val expect = deepLTranslatorClient.requestTranslate(ContentFixture.create(), Language.KOREAN) + val expect = deepLTranslatorClient.requestTranslate(translationRequest()) it("BadRequestException 예외를 던진다.") { val ex = shouldThrow { expect.block() } @@ -85,7 +85,7 @@ class DeepLTranslatorClientTest : DescribeSpec({ statusCode(456) } - val expect = deepLTranslatorClient.requestTranslate(ContentFixture.create(), Language.KOREAN) + val expect = deepLTranslatorClient.requestTranslate(translationRequest()) it("InternalServerError 예외를 던진다.") { val ex = shouldThrow { expect.block() } @@ -98,7 +98,7 @@ class DeepLTranslatorClientTest : DescribeSpec({ statusCode(500) } - val expect = deepLTranslatorClient.requestTranslate(ContentFixture.create(), Language.KOREAN) + val expect = deepLTranslatorClient.requestTranslate(translationRequest()) it("InternalServerError 예외를 던진다.") { val ex = shouldThrow { expect.block() } @@ -109,7 +109,7 @@ class DeepLTranslatorClientTest : DescribeSpec({ context("외부 서버에 연결할 수 없으면") { mockWebServer.shutdown() - val expect = deepLTranslatorClient.requestTranslate(ContentFixture.create(), Language.KOREAN) + val expect = deepLTranslatorClient.requestTranslate(translationRequest()) it("InternalServerError 예외를 던진다.") { val ex = shouldThrow { expect.block() } @@ -131,7 +131,7 @@ class DeepLTranslatorClientTest : DescribeSpec({ delay(200, TimeUnit.MILLISECONDS) } - val expect = delayClient.requestTranslate(ContentFixture.create(), Language.KOREAN) + val expect = delayClient.requestTranslate(translationRequest()) it("InternalServerError 예외를 던진다.") { val ex = shouldThrow { expect.block() } @@ -140,3 +140,10 @@ class DeepLTranslatorClientTest : DescribeSpec({ } } }) + +private fun translationRequest() = TranslatorClientRequest( + newsInformation = NewsInformation("title", "excerpt"), + targetLanguage = Language.KOREAN, + sourceLanguage = Language.ENGLISH, + content = "content" +) From 4e966ee8322edd06262eec1377fa82e71cf173e6 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Fri, 5 Jan 2024 03:30:33 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=EB=84=88=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=20=EC=A0=9C=EA=B1=B0,=20=EC=84=9C=EB=B9=84=EC=8A=A4?= =?UTF-8?q?=EB=A1=9C=20=EB=A1=9C=EC=A7=81=20=EC=9C=84=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NewsAppendContentEventListener.kt | 28 +++++----- .../sc/news/application/NewsCommandService.kt | 21 +++++++ .../application/dto/NewsAppendContentEvent.kt | 12 ---- ...TranslateProgressionStatusChangeService.kt | 24 ++++++++ .../TranslateResultEventListener.kt | 48 ++++++++++++++++ .../application/TranslationCommandService.kt | 12 ++-- .../application/TranslationQueryService.kt | 6 +- .../TranslationResultEventListener.kt | 56 ------------------- ...y.kt => TranslateProgressionRepository.kt} | 4 +- .../application/NewsCommandServiceTest.kt | 23 ++++++++ .../fixture/TranslateProgressionFixture.kt | 21 +++++++ .../TranslationCommandServiceTest.kt | 20 +++---- ...ationProgressionStatusChangeServiceTest.kt | 47 ++++++++++++++++ ...> MemoryTranslateProgressionRepository.kt} | 4 +- 14 files changed, 222 insertions(+), 104 deletions(-) delete mode 100644 src/main/kotlin/kr/galaxyhub/sc/news/application/dto/NewsAppendContentEvent.kt create mode 100644 src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateProgressionStatusChangeService.kt create mode 100644 src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateResultEventListener.kt delete mode 100644 src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationResultEventListener.kt rename src/main/kotlin/kr/galaxyhub/sc/translation/domain/{TranslationProgressionRepository.kt => TranslateProgressionRepository.kt} (69%) create mode 100644 src/test/kotlin/kr/galaxyhub/sc/news/fixture/TranslateProgressionFixture.kt create mode 100644 src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationProgressionStatusChangeServiceTest.kt rename src/test/kotlin/kr/galaxyhub/sc/translation/domain/{MemoryTranslationProgressionRepository.kt => MemoryTranslateProgressionRepository.kt} (85%) diff --git a/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt b/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt index aafcc52..d4bfe0f 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt @@ -1,13 +1,11 @@ package kr.galaxyhub.sc.news.application import io.github.oshai.kotlinlogging.KotlinLogging -import kr.galaxyhub.sc.news.application.dto.NewsAppendContentEvent -import kr.galaxyhub.sc.news.domain.Content -import kr.galaxyhub.sc.news.domain.NewsRepository -import kr.galaxyhub.sc.news.domain.getOrThrow +import java.util.UUID +import kr.galaxyhub.sc.news.domain.Language +import kr.galaxyhub.sc.news.domain.NewsInformation import org.springframework.context.event.EventListener import org.springframework.stereotype.Component -import org.springframework.transaction.annotation.Transactional private val log = KotlinLogging.logger {} @@ -16,20 +14,24 @@ private val log = KotlinLogging.logger {} * 하지만 혹시 모를 상황에 error 로그 남김 */ @Component -@Transactional class NewsAppendContentEventListener( - private val newsRepository: NewsRepository + private val newsCommandService: NewsCommandService, ) { @EventListener fun newsAppendContentEventHandler(event: NewsAppendContentEvent) { val (newsId, newsInformation, content, language) = event - runCatching { - newsRepository.getOrThrow(newsId) - }.onSuccess { - it.addContent(Content(newsId, newsInformation, language, content)) - }.onFailure { - log.error { "뉴스에 컨텐츠를 추가하는 중 예외가 발생했습니다. ${it.message}" } + try { + newsCommandService.appendContent(NewsAppendContentCommand(newsId, newsInformation, content, language)) + } catch (e: Exception) { + log.error { "뉴스에 컨텐츠를 추가하는 중 예외가 발생했습니다. ${e.message}" } } } } + +data class NewsAppendContentEvent( + val newsId: UUID, + val newsInformation: NewsInformation, + val content: String, + val language: Language, +) diff --git a/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsCommandService.kt b/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsCommandService.kt index f8184d1..0f2bd82 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsCommandService.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsCommandService.kt @@ -9,6 +9,7 @@ import kr.galaxyhub.sc.news.domain.NewsInformation import kr.galaxyhub.sc.news.domain.NewsRepository import kr.galaxyhub.sc.news.domain.NewsType import kr.galaxyhub.sc.news.domain.getFetchByIdAndLanguage +import kr.galaxyhub.sc.news.domain.getOrThrow import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -46,6 +47,11 @@ class NewsCommandService( contentByLanguage.updateContent(it) } } + + fun appendContent(command: NewsAppendContentCommand) { + val news = newsRepository.getOrThrow(command.newsId) + news.addContent(command.toContent()) + } } data class NewsCreateCommand( @@ -72,3 +78,18 @@ data class NewsUpdateCommand( val newsInformation: NewsInformation?, val content: String?, ) + +data class NewsAppendContentCommand( + val newsId: UUID, + val newsInformation: NewsInformation, + val content: String, + val language: Language, +) { + + fun toContent() = Content( + newsId = newsId, + newsInformation = newsInformation, + language = language, + content = content + ) +} diff --git a/src/main/kotlin/kr/galaxyhub/sc/news/application/dto/NewsAppendContentEvent.kt b/src/main/kotlin/kr/galaxyhub/sc/news/application/dto/NewsAppendContentEvent.kt deleted file mode 100644 index 993a6bf..0000000 --- a/src/main/kotlin/kr/galaxyhub/sc/news/application/dto/NewsAppendContentEvent.kt +++ /dev/null @@ -1,12 +0,0 @@ -package kr.galaxyhub.sc.news.application.dto - -import java.util.UUID -import kr.galaxyhub.sc.news.domain.Language -import kr.galaxyhub.sc.news.domain.NewsInformation - -data class NewsAppendContentEvent( - val newsId: UUID, - val newsInformation: NewsInformation, - val content: String, - val language: Language -) diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateProgressionStatusChangeService.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateProgressionStatusChangeService.kt new file mode 100644 index 0000000..37f8fe5 --- /dev/null +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateProgressionStatusChangeService.kt @@ -0,0 +1,24 @@ +package kr.galaxyhub.sc.translation.application + +import java.util.UUID +import kr.galaxyhub.sc.translation.domain.TranslateProgressionRepository +import kr.galaxyhub.sc.translation.domain.getOrThrow +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional +class TranslateProgressionStatusChangeService( + private val translateProgressionRepository: TranslateProgressionRepository, +) { + + fun changeComplete(translateProgressionId: UUID) { + val translateProgression = translateProgressionRepository.getOrThrow(translateProgressionId) + translateProgression.changeComplete() + } + + fun changeFailure(translateProgressionId: UUID, message: String?) { + val translateProgression = translateProgressionRepository.getOrThrow(translateProgressionId) + translateProgression.changeFailure(message) + } +} diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateResultEventListener.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateResultEventListener.kt new file mode 100644 index 0000000..550f228 --- /dev/null +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateResultEventListener.kt @@ -0,0 +1,48 @@ +package kr.galaxyhub.sc.translation.application + +import io.github.oshai.kotlinlogging.KotlinLogging +import java.util.UUID +import org.springframework.context.event.EventListener +import org.springframework.stereotype.Component + +private val log = KotlinLogging.logger {} + +/** + * TranslationCommandService.translate 메서드의 트랜잭션이 API 호출보다 늦게 끝나면 예외 발생 가능성 있음. + * 따라서 log를 error로 발생시킴 + * 해당 로그 파악하면 Retry 전략 구성할 것 + * 혹은 TranslationCommandService.translate에서 TransactionalEventListener를 받는곳에서 WebClient 실행 고려 + */ +@Component +class TranslateResultEventListener( + private val translateProgressionStatusChangeService: TranslateProgressionStatusChangeService, +) { + + @EventListener + fun translateSuccessEventHandler(event: TranslateSuccessEvent) { + try { + translateProgressionStatusChangeService.changeComplete(event.translateProgressionId) + } catch (e: Exception) { + log.error { "번역 진행 상황의 상태를 변경 중 예외가 발생했습니다. message=${e.message}" } + } + } + + @EventListener + fun translateFailureEventHandler(event: TranslateFailureEvent) { + try { + translateProgressionStatusChangeService.changeFailure(event.translateProgressionId, event.message) + } catch (e: Exception) { + log.error { "번역 진행 상황의 상태를 변경 중 예외가 발생했습니다. message=${e.message}" } + } + } +} + +data class TranslateSuccessEvent( + val translateProgressionId: UUID, +) + +data class TranslateFailureEvent( + val translateProgressionId: UUID, + val message: String?, +) + diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandService.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandService.kt index 21c7974..bd1b8fb 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandService.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandService.kt @@ -3,13 +3,13 @@ package kr.galaxyhub.sc.translation.application import io.github.oshai.kotlinlogging.KotlinLogging import java.util.UUID import kr.galaxyhub.sc.common.support.validate -import kr.galaxyhub.sc.news.application.dto.NewsAppendContentEvent +import kr.galaxyhub.sc.news.application.NewsAppendContentEvent import kr.galaxyhub.sc.news.domain.Content import kr.galaxyhub.sc.news.domain.Language import kr.galaxyhub.sc.news.domain.NewsRepository import kr.galaxyhub.sc.news.domain.getFetchByIdAndLanguage import kr.galaxyhub.sc.translation.domain.TranslateProgression -import kr.galaxyhub.sc.translation.domain.TranslationProgressionRepository +import kr.galaxyhub.sc.translation.domain.TranslateProgressionRepository import kr.galaxyhub.sc.translation.domain.TranslatorProvider import org.springframework.context.ApplicationEventPublisher import org.springframework.stereotype.Service @@ -20,7 +20,7 @@ private val log = KotlinLogging.logger {} @Service @Transactional class TranslationCommandService( - private val translationProgressionRepository: TranslationProgressionRepository, + private val translateProgressionRepository: TranslateProgressionRepository, private val translatorClients: TranslatorClients, private val newsRepository: NewsRepository, private val eventPublisher: ApplicationEventPublisher, @@ -33,18 +33,18 @@ class TranslationCommandService( val content = news.getContentByLanguage(sourceLanguage) val translateProgression = TranslateProgression(newsId, sourceLanguage, targetLanguage, translatorProvider) - translationProgressionRepository.save(translateProgression) + translateProgressionRepository.save(translateProgression) val translatorClient = translatorClients.getClient(translatorProvider) translatorClient.requestTranslate(content.toRequest(targetLanguage)) .doOnError { log.info { "뉴스 번역 요청이 실패하였습니다. newsId=${newsId}, translateProgressionId=${translateProgression.id} cause=${it.message}" } - eventPublisher.publishEvent(TranslationFailureEvent(translateProgression.id, it.message)) + eventPublisher.publishEvent(TranslateFailureEvent(translateProgression.id, it.message)) } .subscribe { log.info { "뉴스 번역 요청이 완료되었습니다. newsId=${newsId}, translateProgressionId=${translateProgression.id}" } eventPublisher.publishEvent(NewsAppendContentEvent(newsId, it.newsInformation, it.content, it.language)) - eventPublisher.publishEvent(TranslationSuccessEvent(translateProgression.id)) + eventPublisher.publishEvent(TranslateSuccessEvent(translateProgression.id)) } return translateProgression.id } diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationQueryService.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationQueryService.kt index c85c888..fb2c1ee 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationQueryService.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationQueryService.kt @@ -2,7 +2,7 @@ package kr.galaxyhub.sc.translation.application import java.util.UUID import kr.galaxyhub.sc.translation.application.dto.TranslationResponse -import kr.galaxyhub.sc.translation.domain.TranslationProgressionRepository +import kr.galaxyhub.sc.translation.domain.TranslateProgressionRepository import kr.galaxyhub.sc.translation.domain.getOrThrow import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -10,11 +10,11 @@ import org.springframework.transaction.annotation.Transactional @Service @Transactional(readOnly = true) class TranslationQueryService( - private val translationProgressionRepository: TranslationProgressionRepository, + private val translateProgressionRepository: TranslateProgressionRepository, ) { fun findById(translateProgressionId: UUID): TranslationResponse { - return translationProgressionRepository.getOrThrow(translateProgressionId) + return translateProgressionRepository.getOrThrow(translateProgressionId) .let { TranslationResponse.from(it) } } } diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationResultEventListener.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationResultEventListener.kt deleted file mode 100644 index 77c565a..0000000 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslationResultEventListener.kt +++ /dev/null @@ -1,56 +0,0 @@ -package kr.galaxyhub.sc.translation.application - -import io.github.oshai.kotlinlogging.KotlinLogging -import java.util.UUID -import kr.galaxyhub.sc.translation.domain.TranslationProgressionRepository -import kr.galaxyhub.sc.translation.domain.getOrThrow -import org.springframework.context.event.EventListener -import org.springframework.stereotype.Component -import org.springframework.transaction.annotation.Transactional - -private val log = KotlinLogging.logger {} - -/** - * TranslationCommandService.translate 메서드의 트랜잭션이 API 호출보다 늦게 끝나면 예외 발생 가능성 있음. - * 따라서 log를 error로 발생시킴 - * 해당 로그 파악하면 Retry 전략 구성할 것 - * 혹은 TranslationCommandService.translate에서 TransactionalEventListener를 받는곳에서 WebClient 실행 고려 - */ -@Component -@Transactional -class TranslationResultEventListener( - private val translationProgressionRepository: TranslationProgressionRepository -) { - - @EventListener - fun translatorSuccessEventHandler(event: TranslationSuccessEvent) { - runCatching { - translationProgressionRepository.getOrThrow(event.translateProgressionId) - }.onSuccess { - it.changeComplete() - }.onFailure { - log.error { "번역 진행 상황의 상태를 변경 중 예외가 발생했습니다. message=${it.message}" } - } - } - - @EventListener - fun translatorFailureEventHandler(event: TranslationFailureEvent) { - runCatching { - translationProgressionRepository.getOrThrow(event.translateProgressionId) - }.onSuccess { - it.changeFailure(event.message) - }.onFailure { - log.error { "번역 진행 상황의 상태를 변경 중 예외가 발생했습니다. message=${it.message}" } - } - } -} - -data class TranslationSuccessEvent( - val translateProgressionId: UUID, -) - -data class TranslationFailureEvent( - val translateProgressionId: UUID, - val message: String? -) - diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslationProgressionRepository.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslateProgressionRepository.kt similarity index 69% rename from src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslationProgressionRepository.kt rename to src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslateProgressionRepository.kt index f8491f1..432675c 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslationProgressionRepository.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/domain/TranslateProgressionRepository.kt @@ -4,10 +4,10 @@ import java.util.UUID import kr.galaxyhub.sc.common.exception.NotFoundException import org.springframework.data.repository.Repository -fun TranslationProgressionRepository.getOrThrow(translateProgressionId: UUID) = findById(translateProgressionId) +fun TranslateProgressionRepository.getOrThrow(translateProgressionId: UUID) = findById(translateProgressionId) ?: throw NotFoundException("식별자에 대한 번역 진행 상황을 찾을 수 없습니다. id=$translateProgressionId") -interface TranslationProgressionRepository : Repository { +interface TranslateProgressionRepository : Repository { fun save(translateProgression: TranslateProgression): TranslateProgression diff --git a/src/test/kotlin/kr/galaxyhub/sc/news/application/NewsCommandServiceTest.kt b/src/test/kotlin/kr/galaxyhub/sc/news/application/NewsCommandServiceTest.kt index 4705a7f..510245b 100644 --- a/src/test/kotlin/kr/galaxyhub/sc/news/application/NewsCommandServiceTest.kt +++ b/src/test/kotlin/kr/galaxyhub/sc/news/application/NewsCommandServiceTest.kt @@ -9,6 +9,7 @@ import io.kotest.matchers.shouldNotBe import java.time.LocalDateTime import java.time.ZoneId import java.time.ZonedDateTime +import java.util.UUID import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import kr.galaxyhub.sc.news.domain.Language @@ -104,6 +105,20 @@ class NewsCommandServiceTest( } } } + + describe("appendContent") { + val news = newsRepository.save(NewsFixture.create()) + + context("유효한 인자로 메서드를 호출하면") { + newsCommandService.appendContent(newsAppendContentCommand(news.id)) + + it("News에 Content가 추가된다.") { + val content = news.getContentByLanguage(Language.ENGLISH) + + content.content shouldBe "내용" + } + } + } }) private fun newsCreateCommand(originId: Long) = NewsCreateCommand( @@ -116,3 +131,11 @@ private fun newsCreateCommand(originId: Long) = NewsCreateCommand( language = Language.KOREAN, content = "내용" ) + +private fun newsAppendContentCommand(newsId: UUID) = + NewsAppendContentCommand( + newsId = newsId, + newsInformation = NewsInformation("제목", "발췌"), + content = "내용", + language = Language.ENGLISH + ) diff --git a/src/test/kotlin/kr/galaxyhub/sc/news/fixture/TranslateProgressionFixture.kt b/src/test/kotlin/kr/galaxyhub/sc/news/fixture/TranslateProgressionFixture.kt new file mode 100644 index 0000000..65ba89d --- /dev/null +++ b/src/test/kotlin/kr/galaxyhub/sc/news/fixture/TranslateProgressionFixture.kt @@ -0,0 +1,21 @@ +package kr.galaxyhub.sc.news.fixture + +import java.util.UUID +import kr.galaxyhub.sc.news.domain.Language +import kr.galaxyhub.sc.translation.domain.TranslateProgression +import kr.galaxyhub.sc.translation.domain.TranslatorProvider + +object TranslateProgressionFixture { + + fun create( + newsId: UUID = UUID.randomUUID(), + sourceLanguage: Language = Language.ENGLISH, + targetLanguage: Language = Language.KOREAN, + translatorProvider: TranslatorProvider = TranslatorProvider.LOCAL, + ): TranslateProgression = TranslateProgression( + newsId = newsId, + sourceLanguage = sourceLanguage, + targetLanguage = targetLanguage, + translatorProvider = translatorProvider + ) +} diff --git a/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandServiceTest.kt b/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandServiceTest.kt index 73ffd3f..df96566 100644 --- a/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandServiceTest.kt +++ b/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationCommandServiceTest.kt @@ -10,13 +10,13 @@ import io.mockk.mockk import io.mockk.verify import kr.galaxyhub.sc.common.exception.BadRequestException import kr.galaxyhub.sc.common.exception.NotFoundException -import kr.galaxyhub.sc.news.application.dto.NewsAppendContentEvent +import kr.galaxyhub.sc.news.application.NewsAppendContentEvent import kr.galaxyhub.sc.news.domain.Language import kr.galaxyhub.sc.news.domain.MemoryNewsRepository import kr.galaxyhub.sc.news.domain.NewsInformation import kr.galaxyhub.sc.news.fixture.ContentFixture import kr.galaxyhub.sc.news.fixture.NewsFixture -import kr.galaxyhub.sc.translation.domain.MemoryTranslationProgressionRepository +import kr.galaxyhub.sc.translation.domain.MemoryTranslateProgressionRepository import kr.galaxyhub.sc.translation.domain.TranslatorProvider import kr.galaxyhub.sc.translation.domain.getOrThrow import org.springframework.context.ApplicationEventPublisher @@ -24,12 +24,12 @@ import reactor.core.publisher.Mono class TranslationCommandServiceTest : DescribeSpec({ - val translationProgressionRepository = MemoryTranslationProgressionRepository() + val translationProgressionRepository = MemoryTranslateProgressionRepository() val newsRepository = MemoryNewsRepository() val translatorClient = mockk() val eventPublisher = mockk() val translationCommandService = TranslationCommandService( - translationProgressionRepository = translationProgressionRepository, + translateProgressionRepository = translationProgressionRepository, newsRepository = newsRepository, translatorClients = TranslatorClients(mapOf(TranslatorProvider.LOCAL to translatorClient)), eventPublisher = eventPublisher, @@ -78,7 +78,7 @@ class TranslationCommandServiceTest : DescribeSpec({ every { translatorClient.requestTranslate(any()) } returns Mono.fromSupplier { throw IllegalArgumentException() } - every { eventPublisher.publishEvent(ofType()) } returns Unit + every { eventPublisher.publishEvent(ofType()) } returns Unit val translateProgressionId = translationCommandService.translate(command) @@ -89,7 +89,7 @@ class TranslationCommandServiceTest : DescribeSpec({ } it("TranslatorFailureEvent 이벤트가 발행된다.") { - verify { eventPublisher.publishEvent(ofType()) } + verify { eventPublisher.publishEvent(ofType()) } } it("NewsAppendContentEvent 이벤트는 발행되지 않는다.") { @@ -97,7 +97,7 @@ class TranslationCommandServiceTest : DescribeSpec({ } it("TranslationSuccessEvent 이벤트는 발행되지 않는다.") { - verify(exactly = 0) { eventPublisher.publishEvent(ofType()) } + verify(exactly = 0) { eventPublisher.publishEvent(ofType()) } } } @@ -109,7 +109,7 @@ class TranslationCommandServiceTest : DescribeSpec({ val translatorClientResponse = TranslatorClientResponse(NewsInformation("제목", "발췌"), "내용", Language.KOREAN) every { translatorClient.requestTranslate(any()) } returns Mono.just(translatorClientResponse) every { eventPublisher.publishEvent(ofType()) } returns Unit - every { eventPublisher.publishEvent(ofType()) } returns Unit + every { eventPublisher.publishEvent(ofType()) } returns Unit val translateProgressionId = translationCommandService.translate(command) @@ -124,11 +124,11 @@ class TranslationCommandServiceTest : DescribeSpec({ } it("TranslationSuccessEvent 이벤트가 발행된다.") { - verify { eventPublisher.publishEvent(ofType()) } + verify { eventPublisher.publishEvent(ofType()) } } it("TranslatorFailureEvent 이벤트는 발행되지 않는다.") { - verify(exactly = 0) { eventPublisher.publishEvent(ofType()) } + verify(exactly = 0) { eventPublisher.publishEvent(ofType()) } } } } diff --git a/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationProgressionStatusChangeServiceTest.kt b/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationProgressionStatusChangeServiceTest.kt new file mode 100644 index 0000000..ac8ddfb --- /dev/null +++ b/src/test/kotlin/kr/galaxyhub/sc/translation/application/TranslationProgressionStatusChangeServiceTest.kt @@ -0,0 +1,47 @@ +package kr.galaxyhub.sc.translation.application + +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.shouldBe +import kr.galaxyhub.sc.news.fixture.TranslateProgressionFixture +import kr.galaxyhub.sc.translation.domain.MemoryTranslateProgressionRepository +import kr.galaxyhub.sc.translation.domain.TranslateProgression +import kr.galaxyhub.sc.translation.domain.TranslationStatus + +class TranslationProgressionStatusChangeServiceTest( + private val translationProgressionRepository: MemoryTranslateProgressionRepository = MemoryTranslateProgressionRepository(), + private val translateProgressionStatusChangeService: TranslateProgressionStatusChangeService = + TranslateProgressionStatusChangeService(translationProgressionRepository), +) : DescribeSpec({ + + lateinit var translateProgression: TranslateProgression + + beforeContainer { + translateProgression = TranslateProgressionFixture.create() + translationProgressionRepository.save(translateProgression) + } + + afterContainer { + translationProgressionRepository.clear() + } + + describe("changeComplete") { + context("유효한 인자로 메서드를 호출하면") { + translateProgressionStatusChangeService.changeComplete(translateProgression.id) + + it("translateProgression의 translationStatus를 COMPLETE로 변경한다.") { + translateProgression.translationStatus shouldBe TranslationStatus.COMPLETE + } + } + } + + describe("changeFailure") { + context("유효한 인자로 메서드를 호출하면") { + translateProgressionStatusChangeService.changeFailure(translateProgression.id, "예외 발생") + + it("translateProgression의 message를 설정하고, translationStatus를 FAILURE로 변경한다.") { + translateProgression.translationStatus shouldBe TranslationStatus.FAILURE + translateProgression.message shouldBe "예외 발생" + } + } + } +}) diff --git a/src/test/kotlin/kr/galaxyhub/sc/translation/domain/MemoryTranslationProgressionRepository.kt b/src/test/kotlin/kr/galaxyhub/sc/translation/domain/MemoryTranslateProgressionRepository.kt similarity index 85% rename from src/test/kotlin/kr/galaxyhub/sc/translation/domain/MemoryTranslationProgressionRepository.kt rename to src/test/kotlin/kr/galaxyhub/sc/translation/domain/MemoryTranslateProgressionRepository.kt index 2899a04..1168e0b 100644 --- a/src/test/kotlin/kr/galaxyhub/sc/translation/domain/MemoryTranslationProgressionRepository.kt +++ b/src/test/kotlin/kr/galaxyhub/sc/translation/domain/MemoryTranslateProgressionRepository.kt @@ -2,9 +2,9 @@ package kr.galaxyhub.sc.translation.domain import java.util.UUID -class MemoryTranslationProgressionRepository( +class MemoryTranslateProgressionRepository( private val memory: MutableMap = mutableMapOf(), -) : TranslationProgressionRepository { +) : TranslateProgressionRepository { fun clear() = memory.clear() From 5942f0707d398563c7c6c62bb0f73e98ebf82d18 Mon Sep 17 00:00:00 2001 From: seokjin8678 Date: Fri, 5 Jan 2024 10:20:01 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B9=84=EB=8F=99=EA=B8=B0=EB=A1=9C=20=EC=8B=A4=ED=96=89?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/kr/galaxyhub/sc/common/config/AsyncConfig.kt | 8 ++++++++ .../sc/news/application/NewsAppendContentEventListener.kt | 2 ++ .../application/TranslateResultEventListener.kt | 3 +++ 3 files changed, 13 insertions(+) create mode 100644 src/main/kotlin/kr/galaxyhub/sc/common/config/AsyncConfig.kt diff --git a/src/main/kotlin/kr/galaxyhub/sc/common/config/AsyncConfig.kt b/src/main/kotlin/kr/galaxyhub/sc/common/config/AsyncConfig.kt new file mode 100644 index 0000000..b50f65f --- /dev/null +++ b/src/main/kotlin/kr/galaxyhub/sc/common/config/AsyncConfig.kt @@ -0,0 +1,8 @@ +package kr.galaxyhub.sc.common.config + +import org.springframework.context.annotation.Configuration +import org.springframework.scheduling.annotation.EnableAsync + +@EnableAsync +@Configuration +class AsyncConfig diff --git a/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt b/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt index d4bfe0f..634369b 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/news/application/NewsAppendContentEventListener.kt @@ -5,6 +5,7 @@ import java.util.UUID import kr.galaxyhub.sc.news.domain.Language import kr.galaxyhub.sc.news.domain.NewsInformation import org.springframework.context.event.EventListener +import org.springframework.scheduling.annotation.Async import org.springframework.stereotype.Component private val log = KotlinLogging.logger {} @@ -18,6 +19,7 @@ class NewsAppendContentEventListener( private val newsCommandService: NewsCommandService, ) { + @Async @EventListener fun newsAppendContentEventHandler(event: NewsAppendContentEvent) { val (newsId, newsInformation, content, language) = event diff --git a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateResultEventListener.kt b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateResultEventListener.kt index 550f228..9325712 100644 --- a/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateResultEventListener.kt +++ b/src/main/kotlin/kr/galaxyhub/sc/translation/application/TranslateResultEventListener.kt @@ -3,6 +3,7 @@ package kr.galaxyhub.sc.translation.application import io.github.oshai.kotlinlogging.KotlinLogging import java.util.UUID import org.springframework.context.event.EventListener +import org.springframework.scheduling.annotation.Async import org.springframework.stereotype.Component private val log = KotlinLogging.logger {} @@ -18,6 +19,7 @@ class TranslateResultEventListener( private val translateProgressionStatusChangeService: TranslateProgressionStatusChangeService, ) { + @Async @EventListener fun translateSuccessEventHandler(event: TranslateSuccessEvent) { try { @@ -27,6 +29,7 @@ class TranslateResultEventListener( } } + @Async @EventListener fun translateFailureEventHandler(event: TranslateFailureEvent) { try {