ContactUpdater and ContactCacheService

This commit is contained in:
Him188 2021-04-17 17:59:27 +08:00
parent e08fc5d874
commit 3ec8a94096
3 changed files with 100 additions and 9 deletions

View File

@ -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<ContactCacheService>
}
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<net.mamoe.mirai.event.events.FriendInfoChangeEvent> {
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." }
}
}
}

View File

@ -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<FriendInfoImpl>) {
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
}

View File

@ -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)