diff options
Diffstat (limited to 'platform-paper')
2 files changed, 59 insertions, 37 deletions
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/RomanjiConverter.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/RomanjiConverter.kt index c961af8..a50a4aa 100644 --- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/RomanjiConverter.kt +++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/converter/RomanjiConverter.kt @@ -2,6 +2,9 @@ package dev.m1sk9.lunaticChat.paper.converter import dev.m1sk9.lunaticChat.engine.converter.GoogleIMEClient import dev.m1sk9.lunaticChat.engine.converter.KanaConverter +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope import java.util.logging.Logger class RomanjiConverter( @@ -30,52 +33,50 @@ class RomanjiConverter( return null } - val words = input.split(" ") - val results = mutableListOf<String>() + val words = input.split(" ").filter { it.isNotEmpty() } - for (word in words) { - if (word.isEmpty()) { - continue + // The words are independent, and callers convert under a timeout covering the whole + // message. Awaiting them one at a time makes an N-word message cost N round trips, so a + // long message runs out of budget after the first word or two. + val results = + coroutineScope { + words.map { word -> async { convertWord(word) } }.awaitAll() } - // Check cache first - val cached = cache.get(word) - if (cached != null) { - if (debugMode) { - logger.info("Cache hit for word: $word -> $cached") - } - results.add(cached) - continue - } + return results.joinToString(" ") + } - // Pre-validate: Check if the word is valid romaji before attempting conversion - // This prevents partial conversion of English words (e.g., "This" -> "てぃs") - if (!KanaConverter.isValidRomaji(word)) { - if (debugMode) { - logger.info("Word is not valid romaji, keeping original: $word") - } - results.add(word) - continue + private suspend fun convertWord(word: String): String { + cache.get(word)?.let { cached -> + if (debugMode) { + logger.info("Cache hit for word: $word -> $cached") } + return cached + } - // Step 1: Romanji -> Hiragana - val hiragana = KanaConverter.toHiragana(word) + // Pre-validate: Check if the word is valid romaji before attempting conversion + // This prevents partial conversion of English words (e.g., "This" -> "てぃs") + if (!KanaConverter.isValidRomaji(word)) { + if (debugMode) { + logger.info("Word is not valid romaji, keeping original: $word") + } + return word + } - // Step 2: Hiragana -> Kanji/Kana - val converted = - try { - apiClient.convert(hiragana) - } catch (e: Exception) { - logger.warning("Failed to convert $hiragana: ${e.message}") - hiragana // Use hiragana if API fails - } + // Step 1: Romanji -> Hiragana + val hiragana = KanaConverter.toHiragana(word) - // Cache the word-level conversion - cache.put(word, converted) - results.add(converted) - } + // Step 2: Hiragana -> Kanji/Kana + val converted = + try { + apiClient.convert(hiragana) + } catch (e: Exception) { + logger.warning("Failed to convert $hiragana: ${e.message}") + hiragana // Use hiragana if API fails + } - return results.joinToString(" ") + cache.put(word, converted) + return converted } private fun isRomajiOnly(input: String): Boolean = diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/converter/RomanjiConverterTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/converter/RomanjiConverterTest.kt index 1e6d3c0..a7e0a52 100644 --- a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/converter/RomanjiConverterTest.kt +++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/converter/RomanjiConverterTest.kt @@ -7,7 +7,9 @@ import io.mockk.coVerify import io.mockk.every import io.mockk.mockk import io.mockk.verify +import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking +import java.util.concurrent.atomic.AtomicInteger import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNull @@ -298,4 +300,23 @@ class RomanjiConverterTest { assertEquals("おはよう", result) verify(exactly = 1) { cache.put("ohayou", "おはよう") } } + + @Test + fun `words in one message are converted concurrently`() = + runBlocking { + val (converter, _, apiClient) = createConverter() + val inFlight = AtomicInteger(0) + val peakInFlight = AtomicInteger(0) + + coEvery { apiClient.convert(any()) } coAnswers { + peakInFlight.updateAndGet { maxOf(it, inFlight.incrementAndGet()) } + delay(50) + inFlight.decrementAndGet() + "変換" + } + + converter.convert("konnichiwa ohayou arigatou") + + assertEquals(3, peakInFlight.get(), "each word should be in flight at the same time") + } } |
