From 3ec8a94096b95e0ade6351818b2a9462981dda60 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 17 Apr 2021 17:59:27 +0800 Subject: [PATCH] ContactUpdater and ContactCacheService --- .../handler/components/ContactCacheService.kt | 84 +++++++++++++++++++ .../handler/components/ContactUpdater.kt | 23 +++-- .../src/commonTest/kotlin/ScheduledJobTest.kt | 2 +- 3 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 mirai-core/src/commonMain/kotlin/network/handler/components/ContactCacheService.kt diff --git a/mirai-core/src/commonMain/kotlin/network/handler/components/ContactCacheService.kt b/mirai-core/src/commonMain/kotlin/network/handler/components/ContactCacheService.kt new file mode 100644 index 000000000..60329355d --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/network/handler/components/ContactCacheService.kt @@ -0,0 +1,84 @@ +/* + * Copyright 2019-2021 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.internal.network.handler.components + +import net.mamoe.mirai.internal.QQAndroidBot +import net.mamoe.mirai.internal.network.FriendListCache +import net.mamoe.mirai.internal.network.GroupMemberListCaches +import net.mamoe.mirai.internal.network.JsonForCache +import net.mamoe.mirai.internal.network.handler.component.ComponentKey +import net.mamoe.mirai.internal.utils.ScheduledJob +import net.mamoe.mirai.internal.utils.friendCacheFile +import net.mamoe.mirai.utils.createFileIfNotExists +import net.mamoe.mirai.utils.info +import net.mamoe.mirai.utils.loadNotBlankAs +import net.mamoe.mirai.utils.runBIO + +/** + * Maintains cache. Used by [ContactUpdater]. + */ +internal interface ContactCacheService { + val friendListCache: FriendListCache? + val groupMemberListCaches: GroupMemberListCaches? + + fun saveFriendCache() + + companion object : ComponentKey +} + +internal class ContactCacheServiceImpl( + private val bot: QQAndroidBot +) : ContactCacheService { + private val configuration get() = bot.configuration + + /////////////////////////////////////////////////////////////////////////// + // contact cache + /////////////////////////////////////////////////////////////////////////// + + inline val json get() = configuration.json + + override val friendListCache: FriendListCache? by lazy { + if (!configuration.contactListCache.friendListCacheEnabled) return@lazy null + val file = configuration.friendCacheFile() + val ret = file.loadNotBlankAs(FriendListCache.serializer(), JsonForCache) ?: FriendListCache() + + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + bot.eventChannel.parentScope(bot) + .subscribeAlways { + friendListSaver?.notice() + } + ret + } + + override val groupMemberListCaches: GroupMemberListCaches? by lazy { + if (!configuration.contactListCache.groupMemberListCacheEnabled) { + return@lazy null + } + GroupMemberListCaches(bot) + } + + private val friendListSaver: ScheduledJob? by lazy { + if (!configuration.contactListCache.friendListCacheEnabled) return@lazy null + ScheduledJob(bot.coroutineContext, configuration.contactListCache.saveIntervalMillis) { + runBIO { saveFriendCache() } + } + } + + override fun saveFriendCache() { + val friendListCache = friendListCache ?: return + + configuration.friendCacheFile().run { + createFileIfNotExists() + writeText(JsonForCache.encodeToString(FriendListCache.serializer(), friendListCache)) + bot.network.context.logger.info { "Saved ${friendListCache.list.size} friends to local cache." } + } + } + +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/network/handler/components/ContactUpdater.kt b/mirai-core/src/commonMain/kotlin/network/handler/components/ContactUpdater.kt index b57179046..19b5faec1 100644 --- a/mirai-core/src/commonMain/kotlin/network/handler/components/ContactUpdater.kt +++ b/mirai-core/src/commonMain/kotlin/network/handler/components/ContactUpdater.kt @@ -29,6 +29,7 @@ import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl import net.mamoe.mirai.internal.contact.toMiraiFriendInfo import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.handler.component.ComponentKey +import net.mamoe.mirai.internal.network.handler.component.ComponentStorage import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.isValid import net.mamoe.mirai.internal.network.protocol.data.jce.StTroopNum @@ -41,8 +42,11 @@ import net.mamoe.mirai.utils.info import net.mamoe.mirai.utils.retryCatching import net.mamoe.mirai.utils.verbose +/** + * Uses [ContactCacheService] + */ internal interface ContactUpdater { - suspend fun loadAll(registerResp: SvcRespRegister) + suspend fun loadAll(registerResp: SvcRespRegister) // TODO: 2021/4/17 call this fun fun closeAllContacts(e: CancellationException) @@ -50,8 +54,11 @@ internal interface ContactUpdater { } internal class ContactUpdaterImpl( - val bot: QQAndroidBot, + val bot: QQAndroidBot, // not good + val components: ComponentStorage ) : ContactUpdater { + private val cacheService get() = components[ContactCacheService] + @Synchronized override suspend fun loadAll(registerResp: SvcRespRegister) { coroutineScope { @@ -92,14 +99,14 @@ internal class ContactUpdaterImpl( return } - val friendListCache = bot.friendListCache + val friendListCache = cacheService.friendListCache fun updateCacheSeq(list: List) { - bot.friendListCache?.apply { + cacheService.friendListCache?.apply { friendListSeq = registerResp.iLargeSeq timeStamp = registerResp.timeStamp this.list = list - bot.saveFriendCache() + cacheService.saveFriendCache() } } @@ -165,7 +172,7 @@ internal class ContactUpdaterImpl( ) } - val cache = bot.groupMemberListCaches?.get(groupCode) + val cache = cacheService.groupMemberListCaches?.get(groupCode) val members = if (cache != null) { if (cache.isValid(stTroopNum)) { cache.list.asSequence().also { @@ -174,7 +181,7 @@ internal class ContactUpdaterImpl( } else refreshGroupMemberList().also { sequence -> cache.troopMemberNumSeq = dwMemberNumSeq ?: 0 cache.list = sequence.mapTo(ArrayList()) { it as MemberInfoImpl } - bot.groupMemberListCaches!!.reportChanged(groupCode) + cacheService.groupMemberListCaches!!.reportChanged(groupCode) } } else { refreshGroupMemberList() @@ -236,7 +243,7 @@ internal class ContactUpdaterImpl( } logger.info { "Successfully loaded group list: ${troopListData.groups.size} in total." } - bot.groupMemberListCaches?.saveGroupCaches() + cacheService.groupMemberListCaches?.saveGroupCaches() initGroupOk = true } diff --git a/mirai-core/src/commonTest/kotlin/ScheduledJobTest.kt b/mirai-core/src/commonTest/kotlin/ScheduledJobTest.kt index 6e2f7ca70..cfdfc7551 100644 --- a/mirai-core/src/commonTest/kotlin/ScheduledJobTest.kt +++ b/mirai-core/src/commonTest/kotlin/ScheduledJobTest.kt @@ -26,7 +26,7 @@ internal class ScheduledJobTest : AbstractTest() { throwable.printStackTrace() }) val invoked = AtomicInteger(0) - val job = ScheduledJob(scope.coroutineContext, 1 * 1000) { + val job = ScheduledJob(scope.coroutineContext, 1000) { invoked.incrementAndGet() } delay(100)