summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSho Sakuma <me@m1sk9.dev>2026-08-03 00:40:20 +0900
committerSho Sakuma <me@m1sk9.dev>2026-08-05 00:42:22 +0900
commite8b44cf42888cc00c67d885c3d641ca1a8f78034 (patch)
treec71efd14f5c492fa8003a6ac527dd9d7849f6bb5
parent9a57b249dd660c49ac968ab2d3246736772504e1 (diff)
downloadLunaticChat-e8b44cf42888cc00c67d885c3d641ca1a8f78034.tar.gz
LunaticChat-e8b44cf42888cc00c67d885c3d641ca1a8f78034.tar.bz2
LunaticChat-e8b44cf42888cc00c67d885c3d641ca1a8f78034.zip
perf: stop paying at startup for features that are off
Both HTTP consumers - Japanese conversion and the update check - default to disabled, yet onEnable built an HttpClient(CIO) unconditionally, starting a selector and dispatcher pool that a stock install never used and nothing ever closed. It is now created on first use and closed on disable, which also fixes the leak across /reload. LanguageManager parsed and flattened every bundled language file, though getMessage only ever reads the selected one and the English fallback. It now loads exactly those two. Co-Authored-By: Claude <noreply@anthropic.com>
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt9
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt4
-rw-r--r--platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManager.kt7
-rw-r--r--platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManagerTest.kt16
4 files changed, 25 insertions, 11 deletions
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt
index 5b8cab1..7b2f3a0 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/LunaticChat.kt
@@ -45,6 +45,10 @@ class LunaticChat :
private val updateAvailable = AtomicBoolean(false)
+ // Only the Japanese conversion and update-check features make HTTP calls, and both default
+ // to off, so a stock install should not pay for a CIO engine and its thread pool.
+ private val httpClient = lazy { HttpClient(CIO) }
+
override fun onEnable() {
saveDefaultConfig()
val configManager = ConfigManager()
@@ -55,8 +59,6 @@ class LunaticChat :
logger.info("Debug: $configuration")
}
- val httpClient = HttpClient(CIO)
-
// Initialize plugin coroutine scope
pluginScope = PluginCoroutineScope(logger)
@@ -79,7 +81,7 @@ class LunaticChat :
// Check for updates
if (configuration.checkForUpdates) {
- initializeUpdateChecker(httpClient)
+ initializeUpdateChecker(httpClient.value)
}
logger.info("LunaticChat enabled.")
@@ -88,6 +90,7 @@ class LunaticChat :
override fun onDisable() {
pluginScope.cancel()
serviceInitializer.shutdown(services)
+ if (httpClient.isInitialized()) httpClient.value.close()
logger.info("LunaticChat disabled.")
}
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt
index c118c12..6d47788 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/ServiceInitializer.kt
@@ -48,7 +48,7 @@ private data class ChannelComponents(
class ServiceInitializer(
private val plugin: JavaPlugin,
private val configuration: LunaticChatConfiguration,
- private val httpClient: HttpClient,
+ private val httpClient: Lazy<HttpClient>,
private val logger: Logger,
) {
private val handshakeCompleted = AtomicBoolean(false)
@@ -195,7 +195,7 @@ class ServiceInitializer(
val apiClient =
GoogleIMEClient(
timeout = configuration.features.japaneseConversion.apiTimeout.milliseconds,
- httpClient = httpClient,
+ httpClient = httpClient.value,
)
// Initialize Romanji converter
diff --git a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManager.kt b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManager.kt
index dd702ba..19774d2 100644
--- a/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManager.kt
+++ b/platform-paper/src/main/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManager.kt
@@ -37,13 +37,16 @@ class LanguageManager(
private val languageCache = mutableMapOf<Language, Map<String, String>>()
/**
- * Initializes the language manager by loading all language files.
+ * Initializes the language manager by loading the languages [getMessage] can read: the
+ * selected one and the English fallback. Other bundled languages are never consulted, so
+ * parsing and flattening them at startup would be wasted work.
+ *
* This should be called during plugin initialization.
*
* @throws IllegalStateException if the English fallback file is missing or cannot be loaded
*/
fun initialize() {
- Language.entries.forEach { lang ->
+ linkedSetOf(Language.EN, selectedLanguage).forEach { lang ->
try {
val messages = loadLanguageFile(lang)
languageCache[lang] = messages
diff --git a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManagerTest.kt b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManagerTest.kt
index 158d985..6774be8 100644
--- a/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManagerTest.kt
+++ b/platform-paper/src/test/kotlin/dev/m1sk9/lunaticChat/paper/i18n/LanguageManagerTest.kt
@@ -63,13 +63,21 @@ class LanguageManagerTest {
}
@Test
- fun `initialize should load both language files`() {
- val (manager, logger) = createLanguageManager(Language.EN)
+ fun `initialize should load the selected language alongside the English fallback`() {
+ val (manager, logger) = createLanguageManager(Language.JA)
manager.initialize()
- // Both en.yml and ja.yml should be loaded
- assertTrue(logger.infoMessages.any { it.contains("en.yml") })
assertTrue(logger.infoMessages.any { it.contains("ja.yml") })
+ assertTrue(logger.infoMessages.any { it.contains("en.yml") })
+ }
+
+ @Test
+ fun `initialize should not load languages that cannot be read`() {
+ val (manager, logger) = createLanguageManager(Language.EN)
+ manager.initialize()
+
+ // English is both the selection and the fallback, so nothing else is worth parsing.
+ assertTrue(logger.infoMessages.none { it.contains("ja.yml") })
}
@Test