mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-22 13:46:13 +08:00
Components misc implementations including (ABI changes):
- ComponentStorage and its impls - ContactCacheService - ContactUpdater - HeartbeatProcessor - SsoProcessor - QQABot
This commit is contained in:
parent
7f2f1e9759
commit
4f77abca87
@ -105,7 +105,7 @@ internal class QQAndroidBot constructor(
|
|||||||
val components = this // avoid mistakes
|
val components = this // avoid mistakes
|
||||||
set(SsoProcessorContext, SsoProcessorContextImpl(bot))
|
set(SsoProcessorContext, SsoProcessorContextImpl(bot))
|
||||||
set(SsoProcessor, SsoProcessorImpl(get(SsoProcessorContext)))
|
set(SsoProcessor, SsoProcessorImpl(get(SsoProcessorContext)))
|
||||||
set(HeartbeatProcessor, HeartbeatProcessor())
|
set(HeartbeatProcessor, HeartbeatProcessorImpl())
|
||||||
set(KeyRefreshProcessor, KeyRefreshProcessorImpl(networkLogger))
|
set(KeyRefreshProcessor, KeyRefreshProcessorImpl(networkLogger))
|
||||||
set(ConfigPushProcessor, ConfigPushProcessorImpl(networkLogger))
|
set(ConfigPushProcessor, ConfigPushProcessorImpl(networkLogger))
|
||||||
|
|
||||||
|
@ -12,9 +12,13 @@ package net.mamoe.mirai.internal.network.component
|
|||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Facade for [component][ComponentKey]s. Implementation must be thread-safe.
|
* Mediator for [component][ComponentKey]s accessing each other.
|
||||||
|
*
|
||||||
|
* Implementation must be thread-safe.
|
||||||
|
*
|
||||||
* @see MutableComponentStorage
|
* @see MutableComponentStorage
|
||||||
* @see ConcurrentComponentStorage
|
* @see ConcurrentComponentStorage
|
||||||
|
* @see plus
|
||||||
*/
|
*/
|
||||||
internal interface ComponentStorage {
|
internal interface ComponentStorage {
|
||||||
@get:TestOnly
|
@get:TestOnly
|
||||||
@ -24,6 +28,39 @@ internal interface ComponentStorage {
|
|||||||
operator fun <T : Any> get(key: ComponentKey<T>): T
|
operator fun <T : Any> get(key: ComponentKey<T>): T
|
||||||
fun <T : Any> getOrNull(key: ComponentKey<T>): T?
|
fun <T : Any> getOrNull(key: ComponentKey<T>): T?
|
||||||
|
|
||||||
|
val keys: Set<ComponentKey<*>>
|
||||||
|
|
||||||
override fun toString(): String
|
override fun toString(): String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal operator fun ComponentStorage.plus(fallback: ComponentStorage): ComponentStorage =
|
||||||
|
CombinedComponentStorage(this, fallback)
|
||||||
|
|
||||||
|
private class CombinedComponentStorage(
|
||||||
|
val main: ComponentStorage,
|
||||||
|
val fallback: ComponentStorage,
|
||||||
|
) : ComponentStorage {
|
||||||
|
override val keys: Set<ComponentKey<*>> get() = main.keys + fallback.keys
|
||||||
|
override val size: Int get() = keys.size
|
||||||
|
|
||||||
|
override fun <T : Any> get(key: ComponentKey<T>): T {
|
||||||
|
return main.getOrNull(key) ?: fallback.getOrNull(key) ?: main[key] // let `main` throw exception
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any> getOrNull(key: ComponentKey<T>): T? {
|
||||||
|
return main.getOrNull(key) ?: fallback.getOrNull(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = buildString {
|
||||||
|
appendLine("CombinedComponentStorage {")
|
||||||
|
appendLine("* main:")
|
||||||
|
main.toString().lines().forEach {
|
||||||
|
append(" ").appendLine(it)
|
||||||
|
}
|
||||||
|
appendLine("*** fallback:")
|
||||||
|
fallback.toString().lines().forEach {
|
||||||
|
append(" ").appendLine(it)
|
||||||
|
}
|
||||||
|
appendLine("}")
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ internal class ConcurrentComponentStorage(
|
|||||||
) : ComponentStorage, MutableComponentStorage {
|
) : ComponentStorage, MutableComponentStorage {
|
||||||
private val map = ConcurrentHashMap<ComponentKey<*>, Any?>()
|
private val map = ConcurrentHashMap<ComponentKey<*>, Any?>()
|
||||||
|
|
||||||
|
override val keys: Set<ComponentKey<*>> get() = map.keys
|
||||||
override val size: Int get() = map.size
|
override val size: Int get() = map.size
|
||||||
|
|
||||||
override operator fun <T : Any> get(key: ComponentKey<T>): T {
|
override operator fun <T : Any> get(key: ComponentKey<T>): T {
|
||||||
|
@ -9,7 +9,14 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.internal.network.component
|
package net.mamoe.mirai.internal.network.component
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should not be thrown normally.
|
||||||
|
*/
|
||||||
internal data class NoSuchComponentException(
|
internal data class NoSuchComponentException(
|
||||||
val key: ComponentKey<*>,
|
val key: ComponentKey<*>,
|
||||||
val storage: ComponentStorage
|
val storage: ComponentStorage
|
||||||
) : NoSuchElementException("No such component: $key")
|
) : NoSuchElementException() {
|
||||||
|
override val message: String by lazy {
|
||||||
|
"No such component '$key' in storage: \n$storage"
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@ import net.mamoe.mirai.internal.QQAndroidBot
|
|||||||
import net.mamoe.mirai.internal.network.Packet
|
import net.mamoe.mirai.internal.network.Packet
|
||||||
import net.mamoe.mirai.internal.network.component.ComponentKey
|
import net.mamoe.mirai.internal.network.component.ComponentKey
|
||||||
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
import net.mamoe.mirai.internal.network.component.ComponentStorage
|
||||||
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State
|
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State
|
||||||
import net.mamoe.mirai.internal.network.handler.state.JobAttachStateObserver
|
import net.mamoe.mirai.internal.network.handler.state.JobAttachStateObserver
|
||||||
import net.mamoe.mirai.internal.network.handler.state.StateObserver
|
import net.mamoe.mirai.internal.network.handler.state.StateObserver
|
||||||
@ -28,6 +29,13 @@ import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
|
|||||||
import net.mamoe.mirai.utils.MiraiLogger
|
import net.mamoe.mirai.utils.MiraiLogger
|
||||||
import net.mamoe.mirai.utils.info
|
import net.mamoe.mirai.utils.info
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Facade of [ContactUpdater], [OtherClientUpdater], [ConfigPushSyncer].
|
||||||
|
* Handles initialization jobs after successful logon.
|
||||||
|
*
|
||||||
|
* Attached to handler state [NetworkHandler.State.LOADING] [as state observer][asObserver].
|
||||||
|
*/
|
||||||
internal interface BotInitProcessor {
|
internal interface BotInitProcessor {
|
||||||
suspend fun init()
|
suspend fun init()
|
||||||
|
|
||||||
|
@ -22,13 +22,16 @@ import net.mamoe.mirai.utils.loadNotBlankAs
|
|||||||
import net.mamoe.mirai.utils.runBIO
|
import net.mamoe.mirai.utils.runBIO
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maintains cache. Used by [ContactUpdater].
|
* Strategy of caching contacts. Used by [ContactUpdater].
|
||||||
*/
|
*/
|
||||||
internal interface ContactCacheService {
|
internal interface ContactCacheService {
|
||||||
val friendListCache: FriendListCache?
|
val friendListCache: FriendListCache? // from old code
|
||||||
val groupMemberListCaches: GroupMemberListCaches?
|
val groupMemberListCaches: GroupMemberListCaches? // from old code
|
||||||
|
|
||||||
fun saveFriendCache()
|
/**
|
||||||
|
* Implementation does not need to be thread-safe.
|
||||||
|
*/
|
||||||
|
fun saveFriendCache() // from old code
|
||||||
|
|
||||||
companion object : ComponentKey<ContactCacheService>
|
companion object : ComponentKey<ContactCacheService>
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import kotlinx.coroutines.sync.Semaphore
|
|||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.sync.withPermit
|
import kotlinx.coroutines.sync.withPermit
|
||||||
import net.mamoe.mirai.Mirai
|
import net.mamoe.mirai.Mirai
|
||||||
|
import net.mamoe.mirai.contact.Contact
|
||||||
import net.mamoe.mirai.data.FriendInfo
|
import net.mamoe.mirai.data.FriendInfo
|
||||||
import net.mamoe.mirai.data.MemberInfo
|
import net.mamoe.mirai.data.MemberInfo
|
||||||
import net.mamoe.mirai.internal.QQAndroidBot
|
import net.mamoe.mirai.internal.QQAndroidBot
|
||||||
@ -47,11 +48,23 @@ import net.mamoe.mirai.utils.retryCatching
|
|||||||
import net.mamoe.mirai.utils.verbose
|
import net.mamoe.mirai.utils.verbose
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses [ContactCacheService]
|
* Manager of caches for [Contact]s.
|
||||||
|
*
|
||||||
|
* Uses [ContactCacheService].
|
||||||
*/
|
*/
|
||||||
internal interface ContactUpdater {
|
internal interface ContactUpdater {
|
||||||
|
/**
|
||||||
|
* Load all caches to the bot this [ContactUpdater] works for.
|
||||||
|
*
|
||||||
|
* Implementation must be thread-safe.
|
||||||
|
*/
|
||||||
suspend fun loadAll(registerResp: SvcRespRegister)
|
suspend fun loadAll(registerResp: SvcRespRegister)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes all contacts and save them to cache if needed.
|
||||||
|
*
|
||||||
|
* Implementation must be thread-safe.
|
||||||
|
*/
|
||||||
fun closeAllContacts(e: CancellationException)
|
fun closeAllContacts(e: CancellationException)
|
||||||
|
|
||||||
companion object : ComponentKey<ContactUpdater>
|
companion object : ComponentKey<ContactUpdater>
|
||||||
|
@ -15,16 +15,21 @@ import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
|||||||
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||||
import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
|
import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
|
||||||
|
|
||||||
internal class HeartbeatProcessor {
|
internal interface HeartbeatProcessor {
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
suspend fun doHeartbeatNow(networkHandler: NetworkHandler) {
|
suspend fun doHeartbeatNow(networkHandler: NetworkHandler)
|
||||||
|
|
||||||
|
companion object : ComponentKey<HeartbeatProcessor>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class HeartbeatProcessorImpl : HeartbeatProcessor {
|
||||||
|
@Throws(Exception::class)
|
||||||
|
override suspend fun doHeartbeatNow(networkHandler: NetworkHandler) {
|
||||||
StatSvc.SimpleGet(networkHandler.context.bot.client).sendAndExpect(
|
StatSvc.SimpleGet(networkHandler.context.bot.client).sendAndExpect(
|
||||||
networkHandler,
|
networkHandler,
|
||||||
timeoutMillis = networkHandler.context[SsoProcessorContext].configuration.heartbeatTimeoutMillis,
|
timeoutMillis = networkHandler.context[SsoProcessorContext].configuration.heartbeatTimeoutMillis,
|
||||||
retry = 2
|
retry = 2
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : ComponentKey<HeartbeatProcessor>
|
|
||||||
}
|
}
|
@ -28,10 +28,27 @@ internal data class ServerAddress(
|
|||||||
fun toSocketAddress(): InetSocketAddress = InetSocketAddress.createUnresolved(host, port)
|
fun toSocketAddress(): InetSocketAddress = InetSocketAddress.createUnresolved(host, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Self-refillable (similarly circular) queue of servers. Pop each time when trying to connect.
|
||||||
|
*
|
||||||
|
* [Preferred][getPreferred] prevails if present than [DEFAULT_SERVER_LIST].
|
||||||
|
*
|
||||||
|
* *+Implementation must be thread-safe**.
|
||||||
|
*/
|
||||||
internal interface ServerList {
|
internal interface ServerList {
|
||||||
|
/**
|
||||||
|
* Set preferred so not using [DEFAULT_SERVER_LIST].
|
||||||
|
*/
|
||||||
fun setPreferred(list: Collection<ServerAddress>)
|
fun setPreferred(list: Collection<ServerAddress>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Might return [DEFAULT_SERVER_LIST] if not present.
|
||||||
|
*/
|
||||||
fun getPreferred(): Set<ServerAddress>
|
fun getPreferred(): Set<ServerAddress>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refill the queue. Mostly do not call this function.
|
||||||
|
*/
|
||||||
fun refresh()
|
fun refresh()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,9 +77,6 @@ internal interface ServerList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Queue of servers. Pop each time when trying to connect.
|
|
||||||
*/
|
|
||||||
internal class ServerListImpl(
|
internal class ServerListImpl(
|
||||||
initial: Collection<ServerAddress> = emptyList()
|
initial: Collection<ServerAddress> = emptyList()
|
||||||
) : ServerList {
|
) : ServerList {
|
||||||
|
@ -41,7 +41,6 @@ import net.mamoe.mirai.utils.withExceptionCollector
|
|||||||
* Handles login, and acts also as a mediator of [BotInitProcessor], []
|
* Handles login, and acts also as a mediator of [BotInitProcessor], []
|
||||||
*/
|
*/
|
||||||
internal interface SsoProcessor {
|
internal interface SsoProcessor {
|
||||||
val ssoContext: SsoProcessorContext
|
|
||||||
val client: QQAndroidClient
|
val client: QQAndroidClient
|
||||||
val ssoSession: SsoSession
|
val ssoSession: SsoSession
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ internal interface SsoProcessor {
|
|||||||
*
|
*
|
||||||
* E.g. start heartbeat job for [NetworkHandler.State.OK].
|
* E.g. start heartbeat job for [NetworkHandler.State.OK].
|
||||||
*/
|
*/
|
||||||
fun createObserverChain(): StateObserver
|
fun createObserverChain(): StateObserver // todo not used
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do login. Throws [LoginFailedException] if failed
|
* Do login. Throws [LoginFailedException] if failed
|
||||||
@ -69,7 +68,7 @@ internal interface SsoProcessor {
|
|||||||
* Used by [NettyNetworkHandler.StateConnecting].
|
* Used by [NettyNetworkHandler.StateConnecting].
|
||||||
*/
|
*/
|
||||||
internal class SsoProcessorImpl(
|
internal class SsoProcessorImpl(
|
||||||
override val ssoContext: SsoProcessorContext,
|
val ssoContext: SsoProcessorContext,
|
||||||
) : SsoProcessor {
|
) : SsoProcessor {
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user