diff --git a/build.gradle.kts b/build.gradle.kts index 1940430..60ca875 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,7 +3,6 @@ plugins { kotlin("plugin.spring") version "2.2.0" id("org.springframework.boot") version "3.4.4" id("io.spring.dependency-management") version "1.1.7" - id("com.google.cloud.tools.jib") version "3.4.5" id("com.diffplug.spotless") version "7.0.3" } @@ -55,10 +54,3 @@ spotless { ktfmt("0.54").kotlinlangStyle() } } - -jib { - container { - // disable spring devtools - jvmFlags = listOf("-Dspring.devtools.restart.enabled=false") - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/pischule/memevizor/bot/BotConfiguration.kt b/src/main/kotlin/com/pischule/memevizor/bot/BotConfiguration.kt index c7b8fa9..4415e4f 100644 --- a/src/main/kotlin/com/pischule/memevizor/bot/BotConfiguration.kt +++ b/src/main/kotlin/com/pischule/memevizor/bot/BotConfiguration.kt @@ -13,6 +13,8 @@ import com.pischule.memevizor.bot.handler.ThisCommandHandlerService import com.pischule.memevizor.util.getMedia import io.github.oshai.kotlinlogging.KotlinLogging import io.github.oshai.kotlinlogging.withLoggingContext +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -35,13 +37,17 @@ class BotConfiguration( } } + @Bean fun botPollingExecutor(): ExecutorService = Executors.newSingleThreadExecutor() + + @Bean fun botHandlerExecutor(): ExecutorService = Executors.newVirtualThreadPerTaskExecutor() + private fun Bot.Builder.setupDispatchers() = dispatch { - message { withLogAndErrorHandling(message) { thisCommandHandlerService.create(this) } } + message { handleMessage(message) { thisCommandHandlerService.create(this) } } photos { handleMedia() } video { handleMedia() } videoNote { handleMedia() } command("whoami") { - withLogAndErrorHandling(message) { + handleMessage(message) { bot.sendMessage( chatId = ChatId.fromId(message.chat.id), text = "chatId: `${message.chat.id}`\nuserId: `${message.from?.id}`", @@ -52,22 +58,24 @@ class BotConfiguration( } } - private suspend fun MediaHandlerEnvironment<*>.handleMedia() { - withLogAndErrorHandling(message) { mediaHandlerService.create(this) } + private fun MediaHandlerEnvironment<*>.handleMedia() { + handleMessage(message) { mediaHandlerService.create(this) } } - private suspend fun withLogAndErrorHandling(message: Message, block: suspend () -> Unit) { - withLoggingContext( - "message_id" to message.messageId.toString(), - "chat_id" to message.chat.id.toString(), - "from_user_id" to message.from?.id.toString(), - "from_user_username" to message.from?.username.toString(), - "file_id" to (message.getMedia()?.fileId), - ) { - try { - block.invoke() - } catch (e: Exception) { - logger.error(e) { "Error while handling message" } + private fun handleMessage(message: Message, block: () -> Unit) { + botHandlerExecutor().execute { + withLoggingContext( + "message_id" to message.messageId.toString(), + "chat_id" to message.chat.id.toString(), + "from_user_id" to message.from?.id.toString(), + "from_user_username" to message.from?.username.toString(), + "file_id" to (message.getMedia()?.fileId), + ) { + try { + block.invoke() + } catch (e: Exception) { + logger.error(e) { "Error while handling message" } + } } } } diff --git a/src/main/kotlin/com/pischule/memevizor/bot/BotService.kt b/src/main/kotlin/com/pischule/memevizor/bot/BotService.kt index b099499..2d30819 100644 --- a/src/main/kotlin/com/pischule/memevizor/bot/BotService.kt +++ b/src/main/kotlin/com/pischule/memevizor/bot/BotService.kt @@ -4,29 +4,23 @@ import com.github.kotlintelegrambot.Bot import io.github.oshai.kotlinlogging.KotlinLogging import jakarta.annotation.PostConstruct import jakarta.annotation.PreDestroy +import java.util.concurrent.ExecutorService import org.springframework.stereotype.Service private val logger = KotlinLogging.logger {} @Service -class BotService(private val bot: Bot) { - private var pollingThread: Thread? = null +class BotService(private val bot: Bot, private val botPollingExecutor: ExecutorService) { @PostConstruct fun start() { - pollingThread = - Thread { bot.startPolling() } - .apply { - name = "telegram-bot-polling" - start() - } + botPollingExecutor.submit(bot::startPolling) logger.info { "Bot service started" } } @PreDestroy fun stop() { bot.stopPolling() - pollingThread?.join(1000) logger.info { "Bot service stopped" } } } diff --git a/src/main/kotlin/com/pischule/memevizor/bot/handler/MediaHandlerService.kt b/src/main/kotlin/com/pischule/memevizor/bot/handler/MediaHandlerService.kt index 33b91c0..1f2eb11 100644 --- a/src/main/kotlin/com/pischule/memevizor/bot/handler/MediaHandlerService.kt +++ b/src/main/kotlin/com/pischule/memevizor/bot/handler/MediaHandlerService.kt @@ -12,7 +12,7 @@ private val logger = KotlinLogging.logger {} @Service class MediaHandlerService(private val botProps: BotProps) { - suspend fun create(env: MediaHandlerEnvironment<*>) { + fun create(env: MediaHandlerEnvironment<*>) { if (shouldForwardMessage(env)) { forwardMessage(env) } @@ -24,7 +24,7 @@ class MediaHandlerService(private val botProps: BotProps) { return env.message.chat.id != botProps.forwardChatId } - private suspend fun forwardMessage(env: MediaHandlerEnvironment<*>) { + private fun forwardMessage(env: MediaHandlerEnvironment<*>) { env.bot .forwardMessage( chatId = ChatId.fromId(botProps.forwardChatId), @@ -37,7 +37,7 @@ class MediaHandlerService(private val botProps: BotProps) { ) } - private suspend fun reactToMessage(env: MediaHandlerEnvironment<*>, emoji: String) { + private fun reactToMessage(env: MediaHandlerEnvironment<*>, emoji: String) { env.bot .setMessageReaction( chatId = ChatId.fromId(env.message.chat.id), diff --git a/src/main/kotlin/com/pischule/memevizor/bot/handler/ThisCommandHandlerService.kt b/src/main/kotlin/com/pischule/memevizor/bot/handler/ThisCommandHandlerService.kt index f2ac271..bbf08c5 100644 --- a/src/main/kotlin/com/pischule/memevizor/bot/handler/ThisCommandHandlerService.kt +++ b/src/main/kotlin/com/pischule/memevizor/bot/handler/ThisCommandHandlerService.kt @@ -23,7 +23,7 @@ class ThisCommandHandlerService( private val confirmCommands = listOf("this", "!soxok") private val mediaFileName = "media" - suspend fun create(env: MessageHandlerEnvironment) { + fun create(env: MessageHandlerEnvironment) { if (!shouldHandleMessage(env)) return val replyToMessage = env.message.replyToMessage ?: return @@ -54,7 +54,7 @@ class ThisCommandHandlerService( return isApprover && isConfirmCommand } - private suspend fun reactToMessage(env: MessageHandlerEnvironment, emoji: String) { + private fun reactToMessage(env: MessageHandlerEnvironment, emoji: String) { env.bot .setMessageReaction( chatId = ChatId.fromId(env.message.chat.id),