diff --git a/scalabot-app/src/main/kotlin/AppMain.kt b/scalabot-app/src/main/kotlin/AppMain.kt index 4c322ca..0aded3a 100644 --- a/scalabot-app/src/main/kotlin/AppMain.kt +++ b/scalabot-app/src/main/kotlin/AppMain.kt @@ -2,6 +2,7 @@ package net.lamgc.scalabot import kotlinx.coroutines.runBlocking import mu.KotlinLogging +import net.lamgc.scalabot.util.registerShutdownHook import org.telegram.telegrambots.bots.DefaultBotOptions import org.telegram.telegrambots.meta.TelegramBotsApi import org.telegram.telegrambots.meta.generics.BotSession @@ -11,6 +12,7 @@ import kotlin.system.exitProcess private val log = KotlinLogging.logger { } private val launcher = Launcher() + .registerShutdownHook() fun main(args: Array): Unit = runBlocking { log.info { "ScalaBot 正在启动中..." } @@ -21,7 +23,7 @@ fun main(args: Array): Unit = runBlocking { } } -internal class Launcher { +internal class Launcher : AutoCloseable { companion object { @JvmStatic @@ -31,6 +33,7 @@ internal class Launcher { private val botApi = TelegramBotsApi(DefaultBotSession::class.java) private val botSessionMap = mutableMapOf() + @Synchronized fun launch(): Boolean { val botConfigs = loadBotConfig() if (botConfigs.isEmpty()) { @@ -83,6 +86,14 @@ internal class Launcher { log.info { "机器人 `${bot.botUsername}` 已启动." } } + @Synchronized + override fun close() { + botSessionMap.forEach { + log.info { "正在关闭机器人 `${it.key.botUsername}` ..." } + it.value.stop() + log.info { "已关闭机器人 `${it.key.botUsername}`." } + } + } } diff --git a/scalabot-app/src/main/kotlin/util/Utils.kt b/scalabot-app/src/main/kotlin/util/Utils.kt index edcb12d..bd3d91c 100644 --- a/scalabot-app/src/main/kotlin/util/Utils.kt +++ b/scalabot-app/src/main/kotlin/util/Utils.kt @@ -1,5 +1,6 @@ package net.lamgc.scalabot.util +import mu.KotlinLogging import net.lamgc.scalabot.ExtensionPackageFinder import net.lamgc.scalabot.FinderRules import org.eclipse.aether.artifact.Artifact @@ -63,3 +64,33 @@ internal fun File.deepListFiles( internal fun ExtensionPackageFinder.getPriority() = this::class.java.getDeclaredAnnotation(FinderRules::class.java)?.priority ?: throw NoSuchFieldException("Finder did not add `FinderRules` annotation") + +/** + * 为 [AutoCloseable] 对象注册 Jvm Shutdown 钩子. + * @return 返回对象本身, 方便进行链式调用. + */ +fun T.registerShutdownHook(): T { + UtilsInternal.autoCloseableSet.add(this) + return this +} + +private val log = KotlinLogging.logger { } + +private object UtilsInternal { + + val autoCloseableSet = mutableSetOf() + + init { + Runtime.getRuntime().addShutdownHook(Thread({ + log.debug { "Closing registered hook resources..." } + autoCloseableSet.forEach { + try { + it.close() + } catch (e: Exception) { + log.error(e) { "An exception occurred while closing the resource. (Resource: `$it`)" } + } + } + log.debug { "All registered hook resources have been closed." } + }, "Shutdown-AutoCloseable")) + } +} \ No newline at end of file