mirror of
https://github.com/InsanusMokrassar/PlaguPoster.git
synced 2024-11-19 22:33:45 +00:00
add caches
This commit is contained in:
parent
8206131425
commit
b603fa8822
@ -11,7 +11,9 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
api libs.tgbotapi
|
api libs.tgbotapi
|
||||||
api libs.microutils.repos.common
|
api libs.microutils.repos.common
|
||||||
|
api libs.microutils.repos.cache
|
||||||
api libs.kslog
|
api libs.kslog
|
||||||
|
api libs.microutils.koin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
jvmMain {
|
jvmMain {
|
||||||
|
16
common/src/commonMain/kotlin/UseCache.kt
Normal file
16
common/src/commonMain/kotlin/UseCache.kt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package dev.inmo.plaguposter.common
|
||||||
|
|
||||||
|
import org.koin.core.Koin
|
||||||
|
import org.koin.core.module.Module
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.core.scope.Scope
|
||||||
|
|
||||||
|
val Scope.useCache: Boolean
|
||||||
|
get() = getOrNull(named("useCache")) ?: false
|
||||||
|
|
||||||
|
val Koin.useCache: Boolean
|
||||||
|
get() = getOrNull(named("useCache")) ?: false
|
||||||
|
|
||||||
|
fun Module.useCache(useCache: Boolean) {
|
||||||
|
single(named("useCache")) { useCache }
|
||||||
|
}
|
@ -10,6 +10,8 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
|
import kotlinx.serialization.json.booleanOrNull
|
||||||
import org.jetbrains.exposed.sql.Database
|
import org.jetbrains.exposed.sql.Database
|
||||||
import org.koin.core.Koin
|
import org.koin.core.Koin
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
@ -18,6 +20,8 @@ object CommonPlugin : Plugin {
|
|||||||
private val Log = logger
|
private val Log = logger
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||||
single { CoroutineScope(Dispatchers.Default + SupervisorJob()) }
|
single { CoroutineScope(Dispatchers.Default + SupervisorJob()) }
|
||||||
|
val useCache = (params["useCache"] as? JsonPrimitive) ?.booleanOrNull ?: true
|
||||||
|
useCache(useCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||||
|
@ -4,6 +4,9 @@ import com.benasher44.uuid.uuid4
|
|||||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
import dev.inmo.micro_utils.koin.getAllDistinct
|
import dev.inmo.micro_utils.koin.getAllDistinct
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cached
|
||||||
|
import dev.inmo.micro_utils.repos.cache.full.cached
|
||||||
import dev.inmo.micro_utils.repos.deleteById
|
import dev.inmo.micro_utils.repos.deleteById
|
||||||
import dev.inmo.micro_utils.repos.id
|
import dev.inmo.micro_utils.repos.id
|
||||||
import dev.inmo.micro_utils.repos.set
|
import dev.inmo.micro_utils.repos.set
|
||||||
@ -12,6 +15,7 @@ import dev.inmo.micro_utils.repos.value
|
|||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
import dev.inmo.plaguposter.common.ChatConfig
|
import dev.inmo.plaguposter.common.ChatConfig
|
||||||
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
import dev.inmo.plaguposter.common.UnsuccessfulSymbol
|
||||||
|
import dev.inmo.plaguposter.common.useCache
|
||||||
import dev.inmo.plaguposter.posts.models.PostId
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
import dev.inmo.plaguposter.posts.panel.repos.PostsMessages
|
import dev.inmo.plaguposter.posts.panel.repos.PostsMessages
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
@ -93,7 +97,12 @@ object Plugin : Plugin {
|
|||||||
val chatsConfig = koin.get<ChatConfig>()
|
val chatsConfig = koin.get<ChatConfig>()
|
||||||
val config = koin.getOrNull<Config>() ?: Config()
|
val config = koin.getOrNull<Config>() ?: Config()
|
||||||
val api = koin.get<PanelButtonsAPI>()
|
val api = koin.get<PanelButtonsAPI>()
|
||||||
val postsMessages = PostsMessages(koin.get(), koin.get())
|
val basePostsMessages = PostsMessages(koin.get(), koin.get())
|
||||||
|
val postsMessages = if (koin.useCache) {
|
||||||
|
basePostsMessages.cached(FullKVCache(), koin.get())
|
||||||
|
} else {
|
||||||
|
basePostsMessages
|
||||||
|
}
|
||||||
|
|
||||||
postsRepo.newObjectsFlow.subscribeSafelyWithoutExceptions(this) {
|
postsRepo.newObjectsFlow.subscribeSafelyWithoutExceptions(this) {
|
||||||
val firstContent = it.content.first()
|
val firstContent = it.content.first()
|
||||||
|
@ -4,6 +4,7 @@ import dev.inmo.kslog.common.logger
|
|||||||
import dev.inmo.kslog.common.w
|
import dev.inmo.kslog.common.w
|
||||||
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
import dev.inmo.micro_utils.coroutines.runCatchingSafely
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
|
import dev.inmo.micro_utils.koin.singleWithBinds
|
||||||
import dev.inmo.micro_utils.repos.deleteById
|
import dev.inmo.micro_utils.repos.deleteById
|
||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
import dev.inmo.plaguposter.common.SuccessfulSymbol
|
import dev.inmo.plaguposter.common.SuccessfulSymbol
|
||||||
@ -13,6 +14,8 @@ import dev.inmo.plaguposter.common.ChatConfig
|
|||||||
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
import dev.inmo.plagubot.plugins.inline.queries.models.Format
|
||||||
import dev.inmo.plagubot.plugins.inline.queries.models.OfferTemplate
|
import dev.inmo.plagubot.plugins.inline.queries.models.OfferTemplate
|
||||||
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
import dev.inmo.plagubot.plugins.inline.queries.repos.InlineTemplatesRepo
|
||||||
|
import dev.inmo.plaguposter.common.useCache
|
||||||
|
import dev.inmo.plaguposter.posts.cached.CachedPostsRepo
|
||||||
import dev.inmo.plaguposter.posts.repo.*
|
import dev.inmo.plaguposter.posts.repo.*
|
||||||
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
import dev.inmo.plaguposter.posts.sending.PostPublisher
|
||||||
import dev.inmo.tgbotapi.extensions.api.delete
|
import dev.inmo.tgbotapi.extensions.api.delete
|
||||||
@ -44,11 +47,16 @@ object Plugin : Plugin {
|
|||||||
}
|
}
|
||||||
single { get<Json>().decodeFromJsonElement(Config.serializer(), configJson) }
|
single { get<Json>().decodeFromJsonElement(Config.serializer(), configJson) }
|
||||||
single { get<Config>().chats }
|
single { get<Config>().chats }
|
||||||
single { ExposedPostsRepo(database) } binds arrayOf(
|
single { ExposedPostsRepo(database) }
|
||||||
PostsRepo::class,
|
singleWithBinds<PostsRepo> {
|
||||||
ReadPostsRepo::class,
|
val base = get<ExposedPostsRepo>()
|
||||||
WritePostsRepo::class,
|
|
||||||
)
|
if (useCache) {
|
||||||
|
CachedPostsRepo(base, get())
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
}
|
||||||
single {
|
single {
|
||||||
val config = get<Config>()
|
val config = get<Config>()
|
||||||
PostPublisher(get(), get(), config.chats.cacheChatId, config.chats.targetChatId, config.deleteAfterPublishing)
|
PostPublisher(get(), get(), config.chats.cacheChatId, config.chats.targetChatId, config.deleteAfterPublishing)
|
||||||
|
49
posts/src/jvmMain/kotlin/cached/CachedPostsRepo.kt
Normal file
49
posts/src/jvmMain/kotlin/cached/CachedPostsRepo.kt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package dev.inmo.plaguposter.posts.cached
|
||||||
|
|
||||||
|
import com.soywiz.klock.DateTime
|
||||||
|
import dev.inmo.micro_utils.pagination.FirstPagePagination
|
||||||
|
import dev.inmo.micro_utils.pagination.firstPageWithOneElementPagination
|
||||||
|
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
|
||||||
|
import dev.inmo.micro_utils.repos.CRUDRepo
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||||
|
import dev.inmo.micro_utils.repos.cache.full.FullCRUDCacheRepo
|
||||||
|
import dev.inmo.plaguposter.posts.models.NewPost
|
||||||
|
import dev.inmo.plaguposter.posts.models.PostContentInfo
|
||||||
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
|
import dev.inmo.plaguposter.posts.models.RegisteredPost
|
||||||
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
|
import dev.inmo.tgbotapi.types.IdChatIdentifier
|
||||||
|
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class CachedPostsRepo(
|
||||||
|
private val parentRepo: PostsRepo,
|
||||||
|
private val scope: CoroutineScope,
|
||||||
|
private val kvCache: FullKVCache<PostId, RegisteredPost> = FullKVCache()
|
||||||
|
) : PostsRepo, CRUDRepo<RegisteredPost, PostId, NewPost> by FullCRUDCacheRepo(
|
||||||
|
parentRepo,
|
||||||
|
kvCache,
|
||||||
|
scope,
|
||||||
|
{ it.id }
|
||||||
|
) {
|
||||||
|
override val removedPostsFlow: Flow<RegisteredPost> by parentRepo::removedPostsFlow
|
||||||
|
|
||||||
|
override suspend fun getIdByChatAndMessage(chatId: IdChatIdentifier, messageId: MessageIdentifier): PostId? {
|
||||||
|
doForAllWithNextPaging(firstPageWithOneElementPagination) {
|
||||||
|
kvCache.values(it).also {
|
||||||
|
it.results.forEach {
|
||||||
|
return it.takeIf {
|
||||||
|
it.content.any { it.chatId == chatId && it.messageId == messageId }
|
||||||
|
} ?.id ?: return@forEach
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPostCreationTime(postId: PostId): DateTime? = kvCache.get(postId) ?.created
|
||||||
|
|
||||||
|
override suspend fun getFirstMessageInfo(postId: PostId): PostContentInfo? = kvCache.get(postId) ?.content ?.firstOrNull()
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package dev.inmo.plaguposter.ratings.source.repos
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.cache.KeyValueCacheRepo
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||||
|
import dev.inmo.micro_utils.repos.cache.full.cached
|
||||||
|
import dev.inmo.plaguposter.common.ShortMessageInfo
|
||||||
|
import dev.inmo.tgbotapi.types.PollIdentifier
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
|
class CachedPollsToMessagesInfoRepo(
|
||||||
|
private val repo: PollsToMessagesInfoRepo,
|
||||||
|
private val scope: CoroutineScope,
|
||||||
|
private val kvCache: FullKVCache<PollIdentifier, ShortMessageInfo> = FullKVCache()
|
||||||
|
) : PollsToMessagesInfoRepo, KeyValueRepo<PollIdentifier, ShortMessageInfo> by repo.cached(kvCache, scope)
|
@ -0,0 +1,15 @@
|
|||||||
|
package dev.inmo.plaguposter.ratings.source.repos
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||||
|
import dev.inmo.micro_utils.repos.cache.full.cached
|
||||||
|
import dev.inmo.plaguposter.common.ShortMessageInfo
|
||||||
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
|
import dev.inmo.tgbotapi.types.PollIdentifier
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
|
class CachedPollsToPostsIdsRepo(
|
||||||
|
private val repo: PollsToPostsIdsRepo,
|
||||||
|
private val scope: CoroutineScope,
|
||||||
|
private val kvCache: FullKVCache<PollIdentifier, PostId> = FullKVCache()
|
||||||
|
) : PollsToPostsIdsRepo, KeyValueRepo<PollIdentifier, PostId> by repo.cached(kvCache, scope)
|
@ -67,8 +67,29 @@ object Plugin : Plugin {
|
|||||||
get<Json>().decodeFromJsonElement(Config.serializer(), params["ratingsPolls"] ?: error("Unable to load config for rating polls in $params"))
|
get<Json>().decodeFromJsonElement(Config.serializer(), params["ratingsPolls"] ?: error("Unable to load config for rating polls in $params"))
|
||||||
}
|
}
|
||||||
single<RatingsVariants>(ratingVariantsQualifier) { get<Config>().variants }
|
single<RatingsVariants>(ratingVariantsQualifier) { get<Config>().variants }
|
||||||
single<PollsToPostsIdsRepo> { ExposedPollsToPostsIdsRepo(database) }
|
|
||||||
single<PollsToMessagesInfoRepo> { ExposedPollsToMessagesInfoRepo(database) }
|
single { ExposedPollsToPostsIdsRepo(database) }
|
||||||
|
single<PollsToPostsIdsRepo> {
|
||||||
|
val base = get<ExposedPollsToPostsIdsRepo>()
|
||||||
|
|
||||||
|
if (useCache) {
|
||||||
|
CachedPollsToPostsIdsRepo(base, get())
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
single { ExposedPollsToMessagesInfoRepo(database) }
|
||||||
|
single<PollsToMessagesInfoRepo> {
|
||||||
|
val base = get<ExposedPollsToMessagesInfoRepo>()
|
||||||
|
|
||||||
|
if (useCache) {
|
||||||
|
CachedPollsToMessagesInfoRepo(base, get())
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
single<VariantTransformer> {
|
single<VariantTransformer> {
|
||||||
val ratingsSettings = get<RatingsVariants>(ratingVariantsQualifier)
|
val ratingsSettings = get<RatingsVariants>(ratingVariantsQualifier)
|
||||||
VariantTransformer {
|
VariantTransformer {
|
||||||
|
61
ratings/src/commonMain/kotlin/repo/CachedRatingsRepo.kt
Normal file
61
ratings/src/commonMain/kotlin/repo/CachedRatingsRepo.kt
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package dev.inmo.plaguposter.ratings.repo
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
|
||||||
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||||
|
import dev.inmo.micro_utils.repos.cache.full.FullKeyValueCacheRepo
|
||||||
|
import dev.inmo.plaguposter.posts.models.PostId
|
||||||
|
import dev.inmo.plaguposter.ratings.models.Rating
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
|
class CachedRatingsRepo(
|
||||||
|
private val base: RatingsRepo,
|
||||||
|
private val scope: CoroutineScope,
|
||||||
|
private val kvCache: FullKVCache<PostId, Rating> = FullKVCache()
|
||||||
|
) : RatingsRepo, KeyValueRepo<PostId, Rating> by FullKeyValueCacheRepo(base, kvCache, scope) {
|
||||||
|
override suspend fun getPosts(
|
||||||
|
range: ClosedRange<Rating>,
|
||||||
|
reversed: Boolean,
|
||||||
|
count: Int?,
|
||||||
|
exclude: List<PostId>
|
||||||
|
): Map<PostId, Rating> {
|
||||||
|
val result = mutableMapOf<PostId, Rating>()
|
||||||
|
|
||||||
|
doForAllWithNextPaging {
|
||||||
|
kvCache.keys(it).also {
|
||||||
|
it.results.forEach {
|
||||||
|
val rating = kvCache.get(it) ?: return@forEach
|
||||||
|
if (it !in exclude && rating in range) {
|
||||||
|
result[it] = rating
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPostsWithRatingGreaterEq(
|
||||||
|
then: Rating,
|
||||||
|
reversed: Boolean,
|
||||||
|
count: Int?,
|
||||||
|
exclude: List<PostId>
|
||||||
|
): Map<PostId, Rating> = getPosts(
|
||||||
|
then .. Rating(Double.MAX_VALUE),
|
||||||
|
reversed,
|
||||||
|
count,
|
||||||
|
exclude
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun getPostsWithRatingLessEq(
|
||||||
|
then: Rating,
|
||||||
|
reversed: Boolean,
|
||||||
|
count: Int?,
|
||||||
|
exclude: List<PostId>
|
||||||
|
): Map<PostId, Rating> = getPosts(
|
||||||
|
Rating(Double.MIN_VALUE) .. then,
|
||||||
|
reversed,
|
||||||
|
count,
|
||||||
|
exclude
|
||||||
|
)
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
package dev.inmo.plaguposter.ratings
|
package dev.inmo.plaguposter.ratings
|
||||||
|
|
||||||
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
|
||||||
|
import dev.inmo.micro_utils.koin.singleWithBinds
|
||||||
import dev.inmo.micro_utils.repos.unset
|
import dev.inmo.micro_utils.repos.unset
|
||||||
import dev.inmo.plagubot.Plugin
|
import dev.inmo.plagubot.Plugin
|
||||||
|
import dev.inmo.plaguposter.common.useCache
|
||||||
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
import dev.inmo.plaguposter.posts.exposed.ExposedPostsRepo
|
||||||
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
import dev.inmo.plaguposter.posts.repo.PostsRepo
|
||||||
import dev.inmo.plaguposter.ratings.exposed.ExposedRatingsRepo
|
import dev.inmo.plaguposter.ratings.exposed.ExposedRatingsRepo
|
||||||
@ -16,11 +18,16 @@ import org.koin.dsl.binds
|
|||||||
|
|
||||||
object Plugin : Plugin {
|
object Plugin : Plugin {
|
||||||
override fun Module.setupDI(database: Database, params: JsonObject) {
|
override fun Module.setupDI(database: Database, params: JsonObject) {
|
||||||
single { ExposedRatingsRepo(database) } binds arrayOf(
|
single { ExposedRatingsRepo(database) }
|
||||||
RatingsRepo::class,
|
singleWithBinds<RatingsRepo> {
|
||||||
ReadRatingsRepo::class,
|
val base = get<ExposedRatingsRepo>()
|
||||||
WriteRatingsRepo::class,
|
|
||||||
)
|
if (useCache) {
|
||||||
|
CachedRatingsRepo(base, get())
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
override suspend fun BehaviourContext.setupBotPlugin(koin: Koin) {
|
||||||
|
Loading…
Reference in New Issue
Block a user