mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-05 16:29:15 +08:00
Extract sync logic
This commit is contained in:
parent
076cd4997d
commit
f9ddf74d8e
@ -63,6 +63,22 @@ public fun CoroutineScope.childScope(
|
||||
public fun CoroutineContext.childScope(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
): CoroutineScope {
|
||||
return CoroutineScope(this.childScopeContext(coroutineContext))
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a child scope of the receiver context scope.
|
||||
*/
|
||||
public fun CoroutineContext.childScopeContext(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
): CoroutineContext {
|
||||
val ctx = this + coroutineContext
|
||||
return CoroutineScope(ctx + SupervisorJob(ctx.job))
|
||||
return ctx + SupervisorJob(ctx.job)
|
||||
}
|
||||
|
||||
public inline fun <E : U, U : CoroutineContext.Element> CoroutineContext.getOrElse(
|
||||
key: CoroutineContext.Key<E>,
|
||||
default: () -> U
|
||||
): U {
|
||||
return this[key] ?: default()
|
||||
}
|
@ -18,27 +18,24 @@
|
||||
package net.mamoe.mirai.internal
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.event.ConcurrencyKind
|
||||
import net.mamoe.mirai.event.EventChannel
|
||||
import net.mamoe.mirai.event.EventPriority.MONITOR
|
||||
import net.mamoe.mirai.event.GlobalEventChannel
|
||||
import net.mamoe.mirai.event.Listener
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.uin
|
||||
import net.mamoe.mirai.internal.network.component.ConcurrentComponentStorage
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.supervisorJob
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.measureTime
|
||||
|
||||
/**
|
||||
* Protocol-irrelevant implementations
|
||||
*/
|
||||
internal abstract class AbstractBot constructor(
|
||||
final override val configuration: BotConfiguration,
|
||||
final override val id: Long,
|
||||
@ -48,20 +45,17 @@ internal abstract class AbstractBot constructor(
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// FASTEST INIT
|
||||
private val supervisor = SupervisorJob(configuration.parentCoroutineContext[Job])
|
||||
|
||||
final override val logger: MiraiLogger by lazy { configuration.botLoggerSupplier(this) }
|
||||
|
||||
final override val coroutineContext: CoroutineContext = // for id
|
||||
configuration.parentCoroutineContext
|
||||
.plus(supervisor)
|
||||
.plus(
|
||||
configuration.parentCoroutineContext[CoroutineExceptionHandler]
|
||||
?: CoroutineExceptionHandler { _, e ->
|
||||
logger.error("An exception was thrown under a coroutine of Bot", e)
|
||||
}
|
||||
)
|
||||
.plus(CoroutineName("Mirai Bot"))
|
||||
final override val coroutineContext: CoroutineContext = configuration.parentCoroutineContext.childScopeContext(
|
||||
configuration.parentCoroutineContext.getOrElse(CoroutineExceptionHandler) {
|
||||
CoroutineExceptionHandler { _, e ->
|
||||
logger.error("An exception was thrown under a coroutine of Bot", e)
|
||||
}
|
||||
} + CoroutineName("Mirai Bot")
|
||||
)
|
||||
|
||||
abstract val components: ConcurrentComponentStorage
|
||||
|
||||
init {
|
||||
@Suppress("LeakingThis")
|
||||
@ -87,86 +81,6 @@ internal abstract class AbstractBot constructor(
|
||||
final override val asFriend: Friend by lazy { Mirai.newFriend(this, FriendInfoImpl(uin, nick, "")) }
|
||||
final override val asStranger: Stranger by lazy { Mirai.newStranger(bot, StrangerInfoImpl(bot.id, bot.nick)) }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// sync (// TODO: 2021/4/14 extract sync logic
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
val otherClientsLock = Mutex() // lock sync
|
||||
|
||||
// TODO: 2021/4/14 extract offlineListener
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
@Suppress("unused")
|
||||
private val offlineListener: Listener<BotOfflineEvent> =
|
||||
this@AbstractBot.eventChannel.parentJob(supervisor).subscribeAlways(
|
||||
priority = MONITOR,
|
||||
concurrency = ConcurrencyKind.LOCKED
|
||||
) { event ->
|
||||
val bot = bot.asQQAndroidBot()
|
||||
if (
|
||||
!event.bot.isActive // bot closed
|
||||
// || _isConnecting // bot 还在登入 // TODO: 2021/4/14 处理还在登入?
|
||||
) {
|
||||
// Close network to avoid endless reconnection while network is ok
|
||||
// https://github.com/mamoe/mirai/issues/894
|
||||
kotlin.runCatching { network.close(null) }
|
||||
return@subscribeAlways
|
||||
}
|
||||
/*
|
||||
if (network.areYouOk() && event !is BotOfflineEvent.Force && event !is BotOfflineEvent.MsfOffline) {
|
||||
// network 运行正常
|
||||
return@subscribeAlways
|
||||
}*/
|
||||
when (event) {
|
||||
is BotOfflineEvent.Active -> {
|
||||
val cause = event.cause
|
||||
val msg = if (cause == null) "" else " with exception: $cause"
|
||||
bot.logger.info("Bot is closed manually $msg", cause)
|
||||
network.close(null)
|
||||
}
|
||||
is BotOfflineEvent.Force -> {
|
||||
bot.logger.info { "Connection occupied by another android device: ${event.message}" }
|
||||
bot.asQQAndroidBot().accountSecretsFile.delete()
|
||||
bot.client = bot.initClient()
|
||||
if (event.reconnect) {
|
||||
bot.logger.info { "Reconnecting..." }
|
||||
// delay(3000)
|
||||
} else {
|
||||
network.close(null)
|
||||
}
|
||||
}
|
||||
is BotOfflineEvent.MsfOffline,
|
||||
is BotOfflineEvent.Dropped,
|
||||
is BotOfflineEvent.RequireReconnect,
|
||||
is BotOfflineEvent.PacketFactoryErrorCode
|
||||
-> {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
if (event.reconnect) {
|
||||
if (!network.isOk()) {
|
||||
// normally closed
|
||||
return@subscribeAlways
|
||||
}
|
||||
|
||||
val causeMessage = event.castOrNull<BotOfflineEvent.CauseAware>()?.cause?.toString() ?: event.toString()
|
||||
bot.logger.info { "Connection lost, retrying login ($causeMessage)" }
|
||||
|
||||
bot.launch {
|
||||
val success: Boolean
|
||||
val time = measureTime {
|
||||
success = TODO("relogin")
|
||||
}
|
||||
|
||||
if (success) {
|
||||
logger.info { "Reconnected successfully in ${time.toHumanReadableString()}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// network
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -191,7 +105,6 @@ internal abstract class AbstractBot constructor(
|
||||
kotlin.runCatching {
|
||||
network.close(throwable)
|
||||
}
|
||||
offlineListener.cancel(CancellationException("Bot cancelled", throwable))
|
||||
|
||||
// help GC release instances
|
||||
groups.forEach {
|
||||
|
@ -121,7 +121,7 @@ internal open class QQAndroidBot constructor(
|
||||
|
||||
|
||||
private val networkLogger: MiraiLogger by lazy { configuration.networkLoggerSupplier(this) }
|
||||
internal val components: ConcurrentComponentStorage by lazy {
|
||||
override val components: ConcurrentComponentStorage by lazy {
|
||||
ConcurrentComponentStorage().apply {
|
||||
val components = this // avoid mistakes
|
||||
set(SsoProcessorContext, SsoProcessorContextImpl(bot))
|
||||
|
@ -53,6 +53,8 @@ import net.mamoe.mirai.utils.verbose
|
||||
* Uses [ContactCacheService].
|
||||
*/
|
||||
internal interface ContactUpdater {
|
||||
val otherClientsLock: Mutex
|
||||
|
||||
/**
|
||||
* Load all caches to the bot this [ContactUpdater] works for.
|
||||
*
|
||||
@ -75,6 +77,7 @@ internal class ContactUpdaterImpl(
|
||||
val components: ComponentStorage,
|
||||
private val logger: MiraiLogger,
|
||||
) : ContactUpdater {
|
||||
override val otherClientsLock: Mutex = Mutex()
|
||||
private val cacheService get() = components[ContactCacheService]
|
||||
private val lock = Mutex()
|
||||
|
||||
|
@ -25,6 +25,7 @@ import net.mamoe.mirai.internal.contact.appId
|
||||
import net.mamoe.mirai.internal.contact.createOtherClient
|
||||
import net.mamoe.mirai.internal.message.contextualBugReportException
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.components.ContactUpdater
|
||||
import net.mamoe.mirai.internal.network.handler.logger
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
|
||||
@ -36,7 +37,7 @@ internal object MessageSvcRequestPushStatus : IncomingPacketFactory<Packet?>(
|
||||
) {
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {
|
||||
val packet = readUniPacket(RequestPushStatus.serializer())
|
||||
bot.otherClientsLock.withLock {
|
||||
bot.components[ContactUpdater].otherClientsLock.withLock {
|
||||
val instanceInfo = packet.vecInstanceList?.firstOrNull()
|
||||
val appId = instanceInfo?.iAppId ?: 1
|
||||
return when (packet.status.toInt()) {
|
||||
|
@ -29,6 +29,7 @@ import net.mamoe.mirai.internal.contact.createOtherClient
|
||||
import net.mamoe.mirai.internal.message.contextualBugReportException
|
||||
import net.mamoe.mirai.internal.network.*
|
||||
import net.mamoe.mirai.internal.network.components.ContactCacheService
|
||||
import net.mamoe.mirai.internal.network.components.ContactUpdater
|
||||
import net.mamoe.mirai.internal.network.protocol.data.jce.*
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0x769
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.StatSvcGetOnline
|
||||
@ -232,11 +233,6 @@ internal class StatSvc {
|
||||
}
|
||||
|
||||
|
||||
private fun String.ipToLong(): Long {
|
||||
return split('.').foldIndexed(0L) { index: Int, acc: Long, s: String ->
|
||||
acc or (((s.toLongOrNull() ?: 0) shl (index * 16)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal object ReqMSFOffline :
|
||||
@ -283,7 +279,7 @@ internal class StatSvc {
|
||||
IncomingPacketFactory<Packet?>("StatSvc.SvcReqMSFLoginNotify", "StatSvc.SvcReqMSFLoginNotify") {
|
||||
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? =
|
||||
bot.otherClientsLock.withLock {
|
||||
bot.components[ContactUpdater].otherClientsLock.withLock {
|
||||
val notify = readUniPacket(SvcReqMSFLoginNotifyData.serializer())
|
||||
|
||||
val appId = notify.iAppId.toInt()
|
||||
|
Loading…
Reference in New Issue
Block a user