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

refactor: TranslationCommandService translate 메서드 개선 (#76) #77

Merged
merged 3 commits into from
Jan 5, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
8 changes: 8 additions & 0 deletions src/main/kotlin/kr/galaxyhub/sc/common/config/AsyncConfig.kt
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
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.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.scheduling.annotation.Async
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional

private val log = KotlinLogging.logger {}

Expand All @@ -15,20 +15,25 @@ private val log = KotlinLogging.logger {}
* 하지만 혹시 모를 상황에 error 로그 남김
*/
@Component
@Transactional
class NewsAppendContentEventListener(
private val newsRepository: NewsRepository
private val newsCommandService: NewsCommandService,
) {

@Async
@EventListener
fun appendContent(event: NewsAppendContentEvent) {
runCatching {
newsRepository.getOrThrow(event.newsId)
}.onSuccess {
it.addContent(event.content)
}.onFailure {
log.error { "뉴스에 컨텐츠를 추가하는 중 예외가 발생했습니다. ${it.message}" }
fun newsAppendContentEventHandler(event: NewsAppendContentEvent) {
val (newsId, newsInformation, content, language) = event
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,
)
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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(
Expand All @@ -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
)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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 {}

/**
* TranslationCommandService.translate 메서드의 트랜잭션이 API 호출보다 늦게 끝나면 예외 발생 가능성 있음.
* 따라서 log를 error로 발생시킴
* 해당 로그 파악하면 Retry 전략 구성할 것
* 혹은 TranslationCommandService.translate에서 TransactionalEventListener를 받는곳에서 WebClient 실행 고려
*/
@Component
class TranslateResultEventListener(
private val translateProgressionStatusChangeService: TranslateProgressionStatusChangeService,
) {

@Async
@EventListener
fun translateSuccessEventHandler(event: TranslateSuccessEvent) {
try {
translateProgressionStatusChangeService.changeComplete(event.translateProgressionId)
} catch (e: Exception) {
log.error { "번역 진행 상황의 상태를 변경 중 예외가 발생했습니다. message=${e.message}" }
}
}

@Async
@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?,
)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ 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.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.TranslateProgressionRepository
import kr.galaxyhub.sc.translation.domain.TranslatorProvider
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
Expand All @@ -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,
Expand All @@ -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)
translateProgressionRepository.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(TranslateFailureEvent(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(TranslateSuccessEvent(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,
)

Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ 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

@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) }
}
}
Original file line number Diff line number Diff line change
@@ -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<TranslatorClientResponse>

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
)
Original file line number Diff line number Diff line change
@@ -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<TranslatorProvider, TranslatorClient>,
Expand Down

This file was deleted.

This file was deleted.

Loading