package kr.co.vividnext.sodalive.content import kr.co.vividnext.sodalive.i18n.translation.SourceTextNormalizer import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service class LanguageDetectionCacheService( private val languageDetectionResultRepository: LanguageDetectionResultRepository ) { @Transactional fun detectWithCache( query: String, provider: String = DEFAULT_PROVIDER, detector: () -> String? ): String? { val normalizedQuery = SourceTextNormalizer.normalize(query) if (normalizedQuery.isBlank()) return null val sourceHash = SourceTextNormalizer.hash(normalizedQuery) val cached = languageDetectionResultRepository.findBySourceHashAndProviderAndNormalizationVersion( sourceHash = sourceHash, provider = provider, normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) if (cached != null) return cached.detectedLanguage val detectedLanguage = detector()?.takeIf { it.isNotBlank() } ?: return null languageDetectionResultRepository.save( LanguageDetectionResult( sourceHash = sourceHash, sourceTextSample = normalizedQuery.take(MAX_SAMPLE_LENGTH), detectedLanguage = detectedLanguage.lowercase(), provider = provider, confidence = null, normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) ) return detectedLanguage.lowercase() } companion object { const val DEFAULT_PROVIDER = "papago" private const val MAX_SAMPLE_LENGTH = 500 } }