upgrade with potential fix of a lot of reads from disk

This commit is contained in:
InsanusMokrassar 2023-05-26 20:34:23 +06:00
parent 4a90e0f427
commit 3cb74bd587
3 changed files with 30 additions and 31 deletions

View File

@ -1,10 +1,10 @@
[versions] [versions]
kotlin = "1.8.20" kotlin = "1.8.21"
tgbotapi = "7.0.1" tgbotapi = "7.1.3"
microutils = "0.17.6" microutils = "0.18.4"
imageboard = "2.6.0" imageboard = "2.6.0"
krontab = "0.10.0" krontab = "1.0.0"
kslog = "1.1.1" kslog = "1.1.1"
exposed = "0.41.1" exposed = "0.41.1"
psql = "42.6.0" psql = "42.6.0"

View File

@ -1,10 +1,8 @@
import dev.inmo.krontab.utils.asFlow import dev.inmo.krontab.utils.asFlowWithDelays
import dev.inmo.micro_utils.coroutines.* import dev.inmo.micro_utils.coroutines.*
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.*
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache import dev.inmo.micro_utils.repos.cache.full.fullyCached
import dev.inmo.micro_utils.repos.cache.cache.KVCache
import dev.inmo.micro_utils.repos.cache.cached
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedKeyValuesRepo import dev.inmo.micro_utils.repos.exposed.onetomany.ExposedKeyValuesRepo
import dev.inmo.micro_utils.repos.mappers.withMapper import dev.inmo.micro_utils.repos.mappers.withMapper
@ -31,7 +29,6 @@ import models.Config
import net.kodehawa.lib.imageboards.ImageBoard import net.kodehawa.lib.imageboards.ImageBoard
import net.kodehawa.lib.imageboards.boards.DefaultBoards import net.kodehawa.lib.imageboards.boards.DefaultBoards
import net.kodehawa.lib.imageboards.entities.BoardImage import net.kodehawa.lib.imageboards.entities.BoardImage
import kotlin.reflect.full.memberProperties
/** /**
* This method by default expects one argument in [args] field: telegram bot configuration * This method by default expects one argument in [args] field: telegram bot configuration
@ -59,9 +56,9 @@ suspend fun main(args: Array<String>) {
{ json.encodeToString(ChatSettings.serializer(), this) }, { json.encodeToString(ChatSettings.serializer(), this) },
{ ChatId(this) }, { ChatId(this) },
{ json.decodeFromString(ChatSettings.serializer(), this) }, { json.decodeFromString(ChatSettings.serializer(), this) },
).cached(FullKVCache(), scope = scope) ).fullyCached(scope = scope)
val chatsUrlsSeen = ExposedKeyValuesRepo( val chatsUrlsSeenRepo = ExposedKeyValuesRepo(
config.database.database, config.database.database,
{ long("chat_id") }, { long("chat_id") },
{ text("url") }, { text("url") },
@ -71,7 +68,7 @@ suspend fun main(args: Array<String>) {
{ this }, { this },
{ ChatId(this) }, { ChatId(this) },
{ this }, { this },
).cached(KVCache(128), scope = scope) )
val chatsChangingMutex = Mutex() val chatsChangingMutex = Mutex()
val chatsSendingJobs = mutableMapOf<ChatId, Job>() val chatsSendingJobs = mutableMapOf<ChatId, Job>()
@ -82,6 +79,7 @@ suspend fun main(args: Array<String>) {
val me = getMe() val me = getMe()
suspend fun triggerSendForChat(chatId: ChatId, settings: ChatSettings) { suspend fun triggerSendForChat(chatId: ChatId, settings: ChatSettings) {
val seenUrls = chatsUrlsSeenRepo.getAll(chatId).toMutableSet()
val result = let { val result = let {
val result = mutableListOf<BoardImage>() val result = mutableListOf<BoardImage>()
var i = 0 var i = 0
@ -89,7 +87,7 @@ suspend fun main(args: Array<String>) {
val images = settings.makeRequest(i).takeIf { it.isNotEmpty() } ?: break val images = settings.makeRequest(i).takeIf { it.isNotEmpty() } ?: break
result.addAll( result.addAll(
images.filterNot { images.filterNot {
chatsUrlsSeen.contains(chatId, it.url ?: return@filterNot true) seenUrls.contains(it.url ?: return@filterNot true)
} }
) )
i++ i++
@ -98,7 +96,8 @@ suspend fun main(args: Array<String>) {
}.takeIf { it.isNotEmpty() } ?: return }.takeIf { it.isNotEmpty() } ?: return
runCatchingSafely { runCatchingSafely {
val urls = result.map { it.url } val urls = result.map { it.url }
chatsUrlsSeen.add(chatId, urls) chatsUrlsSeenRepo.add(chatId, urls)
seenUrls.addAll(urls)
when { when {
urls.isEmpty() -> return@runCatchingSafely urls.isEmpty() -> return@runCatchingSafely
urls.size == 1 -> sendPhoto( urls.size == 1 -> sendPhoto(
@ -132,23 +131,13 @@ suspend fun main(args: Array<String>) {
chatsChangingMutex.withLock { chatsChangingMutex.withLock {
chatsSendingJobs[chatId] ?.cancel() chatsSendingJobs[chatId] ?.cancel()
settings ?.scheduler ?.let { settings ?.scheduler ?.let {
chatsSendingJobs[chatId] = it.asFlow().subscribeSafelyWithoutExceptions(scope) { chatsSendingJobs[chatId] = it.asFlowWithDelays().subscribeSafelyWithoutExceptions(scope) {
triggerSendForChat(chatId, settings) triggerSendForChat(chatId, settings)
} }
} }
} }
} }
doForAllWithNextPaging {
repo.keys(it).also {
it.results.forEach {
runCatchingSafely {
refreshChatJob(it, null)
}
}
}
}
repo.onNewValue.subscribeSafelyWithoutExceptions(this) { repo.onNewValue.subscribeSafelyWithoutExceptions(this) {
refreshChatJob(it.first, it.second) refreshChatJob(it.first, it.second)
} }
@ -156,12 +145,22 @@ suspend fun main(args: Array<String>) {
refreshChatJob(it, null) refreshChatJob(it, null)
} }
doForAllWithNextPaging {
repo.keys(it).also {
it.results.forEach {
runCatchingSafely {
refreshChatJob(it, null)
}
}
}
}
onCommand(Regex("(help|start)"), requireOnlyCommandInMessage = true) { onCommand(Regex("(help|start)"), requireOnlyCommandInMessage = true) {
reply(it, EnableArgsParser(onlyQueryIsRequired = false).getFormattedHelp().takeIf { it.isNotBlank() } ?: return@onCommand) reply(it, EnableArgsParser().getFormattedHelp().takeIf { it.isNotBlank() } ?: return@onCommand)
} }
onCommand("enable", requireOnlyCommandInMessage = false) { onCommand("enable", requireOnlyCommandInMessage = false) {
val args = it.content.textSources.drop(1).joinToString("") { it.source }.split(" ") val args = it.content.textSources.drop(1).joinToString("") { it.source }.split(" ")
val parser = EnableArgsParser(onlyQueryIsRequired = false) val parser = EnableArgsParser()
runCatchingSafely { runCatchingSafely {
parser.parse(args) parser.parse(args)
repo.set(ChatId(it.chat.id.chatId), parser.resultSettings ?: return@runCatchingSafely) repo.set(ChatId(it.chat.id.chatId), parser.resultSettings ?: return@runCatchingSafely)
@ -188,7 +187,7 @@ suspend fun main(args: Array<String>) {
return@onCommand return@onCommand
} }
} else { } else {
val parser = EnableArgsParser(onlyQueryIsRequired = true, repo.get(ChatId(it.chat.id.chatId)) ?: ChatSettings.DEFAULT) val parser = EnableArgsParser(repo.get(ChatId(it.chat.id.chatId)) ?: ChatSettings.DEFAULT)
runCatchingSafely { runCatchingSafely {
parser.parse(args) parser.parse(args)
parser.resultSettings parser.resultSettings

View File

@ -7,8 +7,7 @@ import net.kodehawa.lib.imageboards.boards.DefaultBoards
import net.kodehawa.lib.imageboards.entities.Rating import net.kodehawa.lib.imageboards.entities.Rating
class EnableArgsParser( class EnableArgsParser(
onlyQueryIsRequired: Boolean, private val base: ChatSettings = ChatSettings.DEFAULT
private val base: ChatSettings = ChatSettings("", null, DefaultBoards.SAFEBOORU)
) : CliktCommand(name = "enable") { ) : CliktCommand(name = "enable") {
private fun <EachT : Any, ValueT> NullableOption<EachT, ValueT>.default( private fun <EachT : Any, ValueT> NullableOption<EachT, ValueT>.default(
value: EachT?, value: EachT?,
@ -26,6 +25,7 @@ class EnableArgsParser(
.check("Count should be in range 1-10") { it in 1 .. 10 } .check("Count should be in range 1-10") { it in 1 .. 10 }
val query by argument() val query by argument()
.multiple(required = true) .multiple(required = true)
.optional()
.help("Your query to booru. Use syntax \"-- -sometag\" to add excluding of some tag in query") .help("Your query to booru. Use syntax \"-- -sometag\" to add excluding of some tag in query")
val krontab by option("-k", "--krontab") val krontab by option("-k", "--krontab")
.transformValues(5) { it.joinToString(" ") } .transformValues(5) { it.joinToString(" ") }
@ -47,7 +47,7 @@ class EnableArgsParser(
override fun run() { override fun run() {
resultSettings = ChatSettings( resultSettings = ChatSettings(
query.filterNot { it.isEmpty() }.joinToString(" ").trim(), query ?.filterNot { it.isEmpty() } ?.joinToString(" ") ?.trim() ?: base.query,
krontab, krontab,
board ?: base.board.boardType as DefaultBoards, board ?: base.board.boardType as DefaultBoards,
count ?: base.count, count ?: base.count,