From e2712ef52e4732a1b782b9eb17024a8dfecd334d Mon Sep 17 00:00:00 2001 From: Hope <34831095+HopeBaron@users.noreply.github.com> Date: Sat, 3 Jul 2021 15:18:36 +0300 Subject: [PATCH 01/13] Add a cache aware rest entity supplier (#338) * add a cahe aware rest supplier/strategy * abstract the new flow creation for storeAndEmit * apply suggestions * Reduce the number of iterations rename storeAndEmit to storeOnEach * update changelog --- CHANGELOG.md | 9 + .../kotlin/supplier/CacheAwareRestSupplier.kt | 163 ++++++++++++++++++ .../kotlin/supplier/EntitySupplyStrategy.kt | 30 ++++ 3 files changed, 202 insertions(+) create mode 100644 core/src/main/kotlin/supplier/CacheAwareRestSupplier.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ecb35fd6cd..07b4022ac0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# 0.7.3 + +## Additions + +* Added a StoreEntitySupplier that will store it's fetched elements in the target cache. +* Added a strategy for a caching rest supplier. +* Added a strategy for a caching with a caching rest fall back strategy. + + # 0.7.2 ## Additions diff --git a/core/src/main/kotlin/supplier/CacheAwareRestSupplier.kt b/core/src/main/kotlin/supplier/CacheAwareRestSupplier.kt new file mode 100644 index 00000000000..4ff6d953895 --- /dev/null +++ b/core/src/main/kotlin/supplier/CacheAwareRestSupplier.kt @@ -0,0 +1,163 @@ +package dev.kord.core.supplier + +import dev.kord.cache.api.DataCache +import dev.kord.cache.api.put +import dev.kord.common.entity.Snowflake +import dev.kord.core.Kord +import dev.kord.core.entity.* +import dev.kord.core.entity.channel.Channel +import dev.kord.core.entity.channel.GuildChannel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.onEach + +/** + * [EntitySupplier] that delegates to another [EntitySupplier] to resolve entities. + * + * Resolved entities will always be stored in [cache] if it wasn't null or empty for flows. + */ +class StoreEntitySupplier( + private val supplier: EntitySupplier, + private val cache: DataCache, + private val kord: Kord +) : EntitySupplier { + + + override val guilds: Flow + get() = storeOnEach(supplier.guilds) { it.data } + + override val regions: Flow + get() = storeOnEach(supplier.regions) { it.data } + + + override suspend fun getGuildOrNull(id: Snowflake): Guild? { + return storeAndReturn(supplier.getGuildOrNull(id)) { it.data } + } + + override suspend fun getGuildPreviewOrNull(guildId: Snowflake): GuildPreview? { + return storeAndReturn(supplier.getGuildPreviewOrNull(guildId)) { it.data } + } + + override suspend fun getGuildWidgetOrNull(guildId: Snowflake): GuildWidget? { + return storeAndReturn(supplier.getGuildWidgetOrNull(guildId)) { it.data } + } + + override suspend fun getChannelOrNull(id: Snowflake): Channel? { + return storeAndReturn(supplier.getChannelOrNull(id)) { it.data } + } + + override fun getGuildChannels(guildId: Snowflake): Flow { + return storeOnEach(supplier.getGuildChannels(guildId)) { it.data } + + } + + override fun getChannelPins(channelId: Snowflake): Flow { + return storeOnEach(supplier.getChannelPins(channelId)) { it.data } + + } + + override suspend fun getMemberOrNull(guildId: Snowflake, userId: Snowflake): Member? { + return storeAndReturn(supplier.getMemberOrNull(guildId, userId)) { it.data } + } + + override suspend fun getMessageOrNull(channelId: Snowflake, messageId: Snowflake): Message? { + return storeAndReturn(supplier.getMessageOrNull(channelId, messageId)) { it.data } + } + + override fun getMessagesAfter(messageId: Snowflake, channelId: Snowflake, limit: Int): Flow { + return storeOnEach(supplier.getMessagesAfter(messageId, channelId, limit)) { it.data } + } + + override fun getMessagesBefore(messageId: Snowflake, channelId: Snowflake, limit: Int): Flow { + return storeOnEach(supplier.getMessagesBefore(messageId, channelId, limit)) { it.data } + } + + override fun getMessagesAround(messageId: Snowflake, channelId: Snowflake, limit: Int): Flow { + return storeOnEach(supplier.getMessagesAround(messageId, channelId, limit)) { it.data } + } + + override suspend fun getSelfOrNull(): User? { + return storeAndReturn(supplier.getSelfOrNull()) { it.data } + } + + override suspend fun getUserOrNull(id: Snowflake): User? { + return storeAndReturn(supplier.getUserOrNull(id)) { it.data } + } + + override suspend fun getRoleOrNull(guildId: Snowflake, roleId: Snowflake): Role? { + return storeAndReturn(supplier.getRoleOrNull(guildId, roleId)) { it.data } + } + + override fun getGuildRoles(guildId: Snowflake): Flow { + return storeOnEach(supplier.getGuildRoles(guildId)) { it.data } + } + + override suspend fun getGuildBanOrNull(guildId: Snowflake, userId: Snowflake): Ban? { + return storeAndReturn(getGuildBanOrNull(guildId, userId)) { it.data } + } + + override fun getGuildBans(guildId: Snowflake): Flow { + return storeOnEach(supplier.getGuildBans(guildId)) { it.data } + } + + override fun getGuildMembers(guildId: Snowflake, limit: Int): Flow { + return storeOnEach(supplier.getGuildMembers(guildId, limit)) { it.data } + } + + override fun getGuildVoiceRegions(guildId: Snowflake): Flow { + return storeOnEach(supplier.getGuildVoiceRegions(guildId)) { it.data } + } + + override suspend fun getEmojiOrNull(guildId: Snowflake, emojiId: Snowflake): GuildEmoji? { + return storeAndReturn(supplier.getEmojiOrNull(guildId, emojiId)) { it.data } + } + + override fun getEmojis(guildId: Snowflake): Flow { + return storeOnEach(supplier.getEmojis(guildId)) { it.data } + + } + + override fun getCurrentUserGuilds(limit: Int): Flow { + return storeOnEach(supplier.getCurrentUserGuilds(limit)) { it.data } + + } + + override fun getChannelWebhooks(channelId: Snowflake): Flow { + return storeOnEach(supplier.getChannelWebhooks(channelId)) { it.data } + } + + override fun getGuildWebhooks(guildId: Snowflake): Flow { + return storeOnEach(supplier.getGuildWebhooks(guildId)) { it.data } + } + + override suspend fun getWebhookOrNull(id: Snowflake): Webhook? { + return storeAndReturn(supplier.getWebhookOrNull(id)) { it.data } + } + + override suspend fun getWebhookWithTokenOrNull(id: Snowflake, token: String): Webhook? { + return storeAndReturn(supplier.getWebhookWithTokenOrNull(id, token)) { it.data } + } + + override suspend fun getTemplateOrNull(code: String): Template? { + return storeAndReturn(supplier.getTemplateOrNull(code)) { it.data } + } + + override fun getTemplates(guildId: Snowflake): Flow