mirror of
https://github.com/pischule/memevizor.git
synced 2025-12-19 06:56:42 +00:00
feat: Switch from coroutines to virtual threads
This commit is contained in:
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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,11 +58,12 @@ 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) {
|
||||
private fun handleMessage(message: Message, block: () -> Unit) {
|
||||
botHandlerExecutor().execute {
|
||||
withLoggingContext(
|
||||
"message_id" to message.messageId.toString(),
|
||||
"chat_id" to message.chat.id.toString(),
|
||||
@@ -71,4 +78,5 @@ class BotConfiguration(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user