refactor(i18n): 공급자 전환과 캐시 선택을 공통 처리로 연결한다
This commit is contained in:
+21
-6
@@ -15,9 +15,14 @@ import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.Creato
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.like.CreatorCommunityLikeRepository
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
||||
import kr.co.vividnext.sodalive.i18n.translation.DetectedLanguage
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageDetectionProvider
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageProviderProperties
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageTranslationTargetType
|
||||
import kr.co.vividnext.sodalive.i18n.translation.PapagoTranslationService
|
||||
import kr.co.vividnext.sodalive.i18n.translation.ResourceTranslationJobScheduler
|
||||
import kr.co.vividnext.sodalive.i18n.translation.SourceTextNormalizer
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslationCoordinator
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslationJobRepository
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslationJobScheduler
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslationMemory
|
||||
@@ -83,6 +88,9 @@ import javax.persistence.EntityManager
|
||||
CreatorCommunityTranslationService::class,
|
||||
TranslationSourceExtractor::class,
|
||||
TranslationReadModelMaterializer::class,
|
||||
TranslationCoordinator::class,
|
||||
LanguageProviderProperties::class,
|
||||
PapagoTranslationService::class,
|
||||
ResourceTranslationJobScheduler::class,
|
||||
TranslationJobScheduler::class,
|
||||
CreatorCommunityLanguageDetectTest.AsyncConfiguration::class
|
||||
@@ -255,7 +263,7 @@ class CreatorCommunityLanguageDetectTest @Autowired constructor(
|
||||
sourceLanguage = "en",
|
||||
targetLanguage = "ko",
|
||||
translatedText = "translated detail content",
|
||||
provider = TranslationReadModelMaterializer.DEFAULT_PROVIDER,
|
||||
provider = "papago",
|
||||
providerVersion = "nmt-v1"
|
||||
)
|
||||
)
|
||||
@@ -719,7 +727,14 @@ class CreatorCommunityLanguageDetectTest @Autowired constructor(
|
||||
|
||||
class ControlledLanguageDetectionCacheService(
|
||||
languageDetectionResultRepository: LanguageDetectionResultRepository
|
||||
) : LanguageDetectionCacheService(languageDetectionResultRepository) {
|
||||
) : LanguageDetectionCacheService(
|
||||
languageDetectionResultRepository,
|
||||
listOf(object : LanguageDetectionProvider {
|
||||
override val providerName = "papago"
|
||||
override fun detect(query: String): String? = null
|
||||
}),
|
||||
LanguageProviderProperties()
|
||||
) {
|
||||
val detections = ConcurrentHashMap<String, String>()
|
||||
val queries = ConcurrentLinkedQueue<String>()
|
||||
private val blockingDetections = ConcurrentHashMap<String, BlockingDetection>()
|
||||
@@ -740,19 +755,19 @@ class ControlledLanguageDetectionCacheService(
|
||||
return ConcurrentDetection(detectedLanguage).also { concurrentDetections[query] = it }
|
||||
}
|
||||
|
||||
override fun detectWithCache(query: String, provider: String, detector: () -> String?): String? {
|
||||
override fun detectWithCache(query: String): DetectedLanguage? {
|
||||
queries.add(query)
|
||||
val concurrentDetection = concurrentDetections[query]
|
||||
if (concurrentDetection != null) {
|
||||
return concurrentDetection.detect()
|
||||
return DetectedLanguage(concurrentDetection.detect(), "papago")
|
||||
}
|
||||
val blockingDetection = blockingDetections[query]
|
||||
if (blockingDetection != null) {
|
||||
blockingDetection.started.countDown()
|
||||
check(blockingDetection.release.await(5, TimeUnit.SECONDS))
|
||||
return blockingDetection.detectedLanguage
|
||||
return DetectedLanguage(blockingDetection.detectedLanguage, "papago")
|
||||
}
|
||||
return detections[query]
|
||||
return detections[query]?.let { DetectedLanguage(it, "papago") }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-3
@@ -4,9 +4,13 @@ import kr.co.vividnext.sodalive.configs.QueryDslConfig
|
||||
import kr.co.vividnext.sodalive.content.theme.AudioContentThemeQueryRepository
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.CreatorCommunity
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.CreatorCommunityRepository
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageProviderProperties
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageTranslationTargetType
|
||||
import kr.co.vividnext.sodalive.i18n.translation.PapagoLanguageDetectionProvider
|
||||
import kr.co.vividnext.sodalive.i18n.translation.PapagoTranslationService
|
||||
import kr.co.vividnext.sodalive.i18n.translation.ResourceTranslationJobScheduler
|
||||
import kr.co.vividnext.sodalive.i18n.translation.SourceTextNormalizer
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslationCoordinator
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslationJobRepository
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslationJobScheduler
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslationJobStatus
|
||||
@@ -67,6 +71,10 @@ import java.util.concurrent.atomic.AtomicInteger
|
||||
QueryDslConfig::class,
|
||||
AudioContentThemeQueryRepository::class,
|
||||
LanguageDetectionCacheService::class,
|
||||
LanguageProviderProperties::class,
|
||||
PapagoLanguageDetectionProvider::class,
|
||||
PapagoTranslationService::class,
|
||||
TranslationCoordinator::class,
|
||||
LanguageDetectListener::class,
|
||||
CreatorCommunityTranslationService::class,
|
||||
TranslationSourceExtractor::class,
|
||||
@@ -82,6 +90,7 @@ class CreatorCommunityLanguageDetectionCacheConcurrencyTest @Autowired construct
|
||||
private val translationJobRepository: TranslationJobRepository,
|
||||
private val languageDetectionCacheService: LanguageDetectionCacheService,
|
||||
private val languageDetectListener: LanguageDetectListener,
|
||||
private val papagoLanguageDetectionProvider: PapagoLanguageDetectionProvider,
|
||||
transactionManager: PlatformTransactionManager
|
||||
) {
|
||||
private val requiresNewTransactionTemplate = TransactionTemplate(transactionManager).apply {
|
||||
@@ -92,8 +101,7 @@ class CreatorCommunityLanguageDetectionCacheConcurrencyTest @Autowired construct
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
papagoRequests = ControlledPapagoRequestFactory()
|
||||
val listener: LanguageDetectListener = AopTestUtils.getTargetObject(languageDetectListener)
|
||||
ReflectionTestUtils.setField(listener, "restTemplate", RestTemplate(papagoRequests))
|
||||
ReflectionTestUtils.setField(papagoLanguageDetectionProvider, "restTemplate", RestTemplate(papagoRequests))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -232,7 +240,7 @@ class CreatorCommunityLanguageDetectionCacheConcurrencyTest @Autowired construct
|
||||
val rows = requiresNewTransactionTemplate.execute {
|
||||
languageDetectionResultRepository.findAll().filter {
|
||||
it.sourceHash == SourceTextNormalizer.hash(content) &&
|
||||
it.provider == LanguageDetectionCacheService.DEFAULT_PROVIDER &&
|
||||
it.provider == "papago" &&
|
||||
it.normalizationVersion == SourceTextNormalizer.NORMALIZATION_VERSION
|
||||
}
|
||||
}.orEmpty()
|
||||
|
||||
+18
-10
@@ -1,5 +1,8 @@
|
||||
package kr.co.vividnext.sodalive.content
|
||||
|
||||
import kr.co.vividnext.sodalive.i18n.translation.DetectedLanguage
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageDetectionProvider
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageProviderProperties
|
||||
import kr.co.vividnext.sodalive.i18n.translation.SourceTextNormalizer
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
@@ -10,7 +13,8 @@ class LanguageDetectionCacheServiceTest {
|
||||
@Test
|
||||
fun shouldReuseCachedLanguageDetectionForSameNormalizedText() {
|
||||
val repository = Mockito.mock(LanguageDetectionResultRepository::class.java)
|
||||
val service = LanguageDetectionCacheService(repository)
|
||||
var providerCalls = 0
|
||||
val service = service(repository) { providerCalls++; "ko" }
|
||||
val sourceHash = SourceTextNormalizer.hash("Hello world")
|
||||
|
||||
Mockito.`when`(
|
||||
@@ -30,13 +34,9 @@ class LanguageDetectionCacheServiceTest {
|
||||
)
|
||||
)
|
||||
|
||||
var providerCalls = 0
|
||||
val detected = service.detectWithCache("Hello world") {
|
||||
providerCalls++
|
||||
"ko"
|
||||
}
|
||||
val detected = service.detectWithCache("Hello world")
|
||||
|
||||
assertEquals("en", detected)
|
||||
assertEquals(DetectedLanguage("en", "papago"), detected)
|
||||
assertEquals(0, providerCalls)
|
||||
Mockito.verify(repository).findBySourceHashAndProviderAndNormalizationVersion(
|
||||
sourceHash = sourceHash,
|
||||
@@ -50,7 +50,7 @@ class LanguageDetectionCacheServiceTest {
|
||||
@DisplayName("최초 캐시 저장 경합에서는 저장된 승자의 감지 언어를 반환한다")
|
||||
fun shouldReturnStoredWinnerAfterInitialCacheInsert() {
|
||||
val repository = Mockito.mock(LanguageDetectionResultRepository::class.java)
|
||||
val service = LanguageDetectionCacheService(repository)
|
||||
val service = service(repository) { "en" }
|
||||
val sourceHash = SourceTextNormalizer.hash("Hello world")
|
||||
|
||||
Mockito.`when`(
|
||||
@@ -78,9 +78,9 @@ class LanguageDetectionCacheServiceTest {
|
||||
)
|
||||
).thenReturn("ko")
|
||||
|
||||
val detected = service.detectWithCache("Hello world") { "en" }
|
||||
val detected = service.detectWithCache("Hello world")
|
||||
|
||||
assertEquals("ko", detected)
|
||||
assertEquals(DetectedLanguage("ko", "papago"), detected)
|
||||
Mockito.verify(repository).findBySourceHashAndProviderAndNormalizationVersion(
|
||||
sourceHash = sourceHash,
|
||||
provider = "papago",
|
||||
@@ -101,4 +101,12 @@ class LanguageDetectionCacheServiceTest {
|
||||
)
|
||||
Mockito.verifyNoMoreInteractions(repository)
|
||||
}
|
||||
|
||||
private fun service(repository: LanguageDetectionResultRepository, detect: () -> String?): LanguageDetectionCacheService {
|
||||
val provider = object : LanguageDetectionProvider {
|
||||
override val providerName = "papago"
|
||||
override fun detect(query: String) = detect()
|
||||
}
|
||||
return LanguageDetectionCacheService(repository, listOf(provider), LanguageProviderProperties())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user