diff --git a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt index 94ce7f2..5a4e01c 100644 --- a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt +++ b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/DefaultMessageContentCache.kt @@ -10,17 +10,20 @@ import dev.inmo.tgbotapi.types.InputMedia.* import dev.inmo.tgbotapi.types.MessageIdentifier import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent +import dev.inmo.tgbotapi.utils.StorageFile +import dev.inmo.tgbotapi.utils.asInput import io.ktor.utils.io.cancel +import io.ktor.utils.io.core.Input -class DefaultMessageContentCache( +class DefaultMessageContentCache( private val bot: TelegramBot, - private val simpleMessageContentCache: MessageContentCache, - private val messagesFilesCache: MessagesFilesCache, - private val filesRefreshingChatId: ChatId + private val filesRefreshingChatId: ChatId, + private val simpleMessageContentCache: MessagesSimpleCache = InMemoryMessagesSimpleCache(), + private val messagesFilesCache: MessagesFilesCache = InMemoryMessagesFilesCache() ) : MessageContentCache { override suspend fun save(chatId: ChatId, messageId: MessageIdentifier, content: MessageContent): Boolean { - runCatching { - if (content is MediaContent) { + return when (content) { + is MediaContent -> { val extendedInfo = bot.execute( GetFile(content.media.fileId) ) @@ -29,15 +32,33 @@ class DefaultMessageContentCache( extendedInfo.filePath ) ) - messagesFilesCache.set(chatId, messageId, extendedInfo.fileName, allocator) + + save(chatId, messageId, content, extendedInfo.fileName) { + allocator.invoke().asInput() + } } + else -> simpleMessageContentCache.runCatching { + set(chatId, messageId, content) + }.isSuccess + } + } + + override suspend fun save( + chatId: ChatId, + messageId: MessageIdentifier, + content: MediaContent, + filename: String, + inputAllocator: suspend () -> Input + ): Boolean { + runCatching { + messagesFilesCache.set(chatId, messageId, filename, inputAllocator) }.onFailure { return false } - return simpleMessageContentCache.save( - chatId, messageId, content - ) + return simpleMessageContentCache.runCatching { + set(chatId, messageId, content) + }.isSuccess } override suspend fun get(chatId: ChatId, messageId: MessageIdentifier): MessageContent? { @@ -101,7 +122,7 @@ class DefaultMessageContentCache( } ) - simpleMessageContentCache.save(chatId, messageId, newContent.content) + simpleMessageContentCache.set(chatId, messageId, newContent.content) return newContent.content } } diff --git a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessageContentCache.kt b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessageContentCache.kt index 48fc69d..2718920 100644 --- a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessageContentCache.kt +++ b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessageContentCache.kt @@ -2,10 +2,19 @@ package dev.inmo.tgbotapi.libraries.cache.media.common import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.MessageIdentifier +import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent +import io.ktor.utils.io.core.Input interface MessageContentCache { suspend fun save(chatId: ChatId, messageId: MessageIdentifier, content: MessageContent): Boolean + suspend fun save( + chatId: ChatId, + messageId: MessageIdentifier, + content: MediaContent, + filename: String, + inputAllocator: suspend () -> Input + ): Boolean suspend fun get(chatId: ChatId, messageId: MessageIdentifier): MessageContent? suspend fun contains(chatId: ChatId, messageId: MessageIdentifier): Boolean suspend fun remove(chatId: ChatId, messageId: MessageIdentifier) diff --git a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessagesFilesCache.kt b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessagesFilesCache.kt index 2459366..a23fa5d 100644 --- a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessagesFilesCache.kt +++ b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessagesFilesCache.kt @@ -2,13 +2,16 @@ package dev.inmo.tgbotapi.libraries.cache.media.common import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.MessageIdentifier -import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator import dev.inmo.tgbotapi.utils.StorageFile -import io.ktor.util.toByteArray -import io.ktor.utils.io.ByteReadChannel +import io.ktor.utils.io.core.* interface MessagesFilesCache { - suspend fun set(chatId: ChatId, messageIdentifier: MessageIdentifier, filename: String, byteReadChannelAllocator: ByteReadChannelAllocator) + suspend fun set( + chatId: ChatId, + messageIdentifier: MessageIdentifier, + filename: String, + inputAllocator: suspend () -> Input + ) suspend fun get(chatId: ChatId, messageIdentifier: MessageIdentifier): StorageFile? suspend fun remove(chatId: ChatId, messageIdentifier: MessageIdentifier) suspend fun contains(chatId: ChatId, messageIdentifier: MessageIdentifier): Boolean @@ -26,11 +29,11 @@ class InMemoryMessagesFilesCache : MessagesFilesCache { chatId: ChatId, messageIdentifier: MessageIdentifier, filename: String, - byteReadChannelAllocator: ByteReadChannelAllocator + inputAllocator: suspend () -> Input ) { map[chatId to messageIdentifier] = StorageFile( filename, - byteReadChannelAllocator.invoke() + inputAllocator().readBytes() ) } diff --git a/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessagesSimpleCache.kt b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessagesSimpleCache.kt new file mode 100644 index 0000000..a325fe2 --- /dev/null +++ b/cache/content/common/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/MessagesSimpleCache.kt @@ -0,0 +1,48 @@ +package dev.inmo.tgbotapi.libraries.cache.media.common + +import dev.inmo.tgbotapi.types.ChatId +import dev.inmo.tgbotapi.types.MessageIdentifier +import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent +import dev.inmo.tgbotapi.utils.StorageFile +import io.ktor.utils.io.core.* + +interface MessagesSimpleCache { + suspend fun set( + chatId: ChatId, + messageIdentifier: MessageIdentifier, + content: MessageContent + ) + suspend fun get(chatId: ChatId, messageIdentifier: MessageIdentifier): MessageContent? + suspend fun remove(chatId: ChatId, messageIdentifier: MessageIdentifier) + suspend fun contains(chatId: ChatId, messageIdentifier: MessageIdentifier): Boolean +} + +/** + * It is not recommended to use in production realization of [MessagesFilesCache] which has been created for fast + * start of application creation with usage of [MessageContentCache] with aim to replace this realization by some + * disks-oriented one + */ +class InMemoryMessagesSimpleCache : MessagesSimpleCache { + private val map = mutableMapOf, MessageContent>() + + override suspend fun set( + chatId: ChatId, + messageIdentifier: MessageIdentifier, + content: MessageContent + ) { + map[chatId to messageIdentifier] = content + } + + override suspend fun get(chatId: ChatId, messageIdentifier: MessageIdentifier): MessageContent? { + return map[chatId to messageIdentifier] + } + + override suspend fun remove(chatId: ChatId, messageIdentifier: MessageIdentifier) { + map.remove(chatId to messageIdentifier) + } + + override suspend fun contains(chatId: ChatId, messageIdentifier: MessageIdentifier): Boolean { + return map.contains(chatId to messageIdentifier) + } + +} diff --git a/cache/content/common/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/InFilesMessagesFilesCache.kt b/cache/content/common/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/InFilesMessagesFilesCache.kt index c893888..9244e6c 100644 --- a/cache/content/common/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/InFilesMessagesFilesCache.kt +++ b/cache/content/common/src/jvmMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/common/InFilesMessagesFilesCache.kt @@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.libraries.cache.media.common import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.MessageIdentifier import dev.inmo.tgbotapi.utils.* +import io.ktor.utils.io.core.Input import io.ktor.utils.io.core.copyTo import io.ktor.utils.io.streams.asInput import io.ktor.utils.io.streams.asOutput @@ -42,13 +43,13 @@ class InFilesMessagesFilesCache( chatId: ChatId, messageIdentifier: MessageIdentifier, filename: String, - byteReadChannelAllocator: ByteReadChannelAllocator + inputAllocator: suspend () -> Input ) { val fullFileName = fileName(chatId, messageIdentifier, filename) val file = File(folderFile, fullFileName).apply { delete() } - byteReadChannelAllocator.invoke().asInput().use { input -> + inputAllocator().use { input -> file.outputStream().asOutput().use { output -> input.copyTo(output) } diff --git a/cache/content/micro_utils/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/micro_utils/SimpleKeyValueMessageContentCache.kt b/cache/content/micro_utils/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/micro_utils/SimpleKeyValueMessageContentCache.kt index 86f6f6d..0cf0ce0 100644 --- a/cache/content/micro_utils/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/micro_utils/SimpleKeyValueMessageContentCache.kt +++ b/cache/content/micro_utils/src/commonMain/kotlin/dev/inmo/tgbotapi/libraries/cache/media/micro_utils/SimpleKeyValueMessageContentCache.kt @@ -2,7 +2,7 @@ package dev.inmo.tgbotapi.libraries.cache.media.micro_utils import dev.inmo.micro_utils.repos.* import dev.inmo.micro_utils.repos.mappers.withMapper -import dev.inmo.tgbotapi.libraries.cache.media.common.MessageContentCache +import dev.inmo.tgbotapi.libraries.cache.media.common.MessagesSimpleCache import dev.inmo.tgbotapi.types.ChatId import dev.inmo.tgbotapi.types.MessageIdentifier import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent @@ -16,23 +16,21 @@ import kotlin.jvm.JvmName class SimpleKeyValueMessageContentCache( private val keyValueRepo: KeyValueRepo, MessageContent> -) : MessageContentCache { - override suspend fun save(chatId: ChatId, messageId: MessageIdentifier, content: MessageContent): Boolean { - return keyValueRepo.runCatching { - set(chatId to messageId, content) - }.isSuccess +) : MessagesSimpleCache { + override suspend fun set(chatId: ChatId, messageIdentifier: MessageIdentifier, content: MessageContent) { + keyValueRepo.set(chatId to messageIdentifier, content) } - override suspend fun get(chatId: ChatId, messageId: MessageIdentifier): MessageContent? { - return keyValueRepo.get(chatId to messageId) + override suspend fun get(chatId: ChatId, messageIdentifier: MessageIdentifier): MessageContent? { + return keyValueRepo.get(chatId to messageIdentifier) } - override suspend fun contains(chatId: ChatId, messageId: MessageIdentifier): Boolean { - return keyValueRepo.contains(chatId to messageId) + override suspend fun contains(chatId: ChatId, messageIdentifier: MessageIdentifier): Boolean { + return keyValueRepo.contains(chatId to messageIdentifier) } - override suspend fun remove(chatId: ChatId, messageId: MessageIdentifier) { - keyValueRepo.unset(chatId to messageId) + override suspend fun remove(chatId: ChatId, messageIdentifier: MessageIdentifier) { + keyValueRepo.unset(chatId to messageIdentifier) } }