Improve logging

This commit is contained in:
Him188 2021-04-25 18:37:21 +08:00
parent 5fa54114c1
commit a7a4879d05
16 changed files with 210 additions and 124 deletions

View File

@ -15,7 +15,8 @@ import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import net.mamoe.mirai.event.events.BotEvent import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.internal.event.broadcastInternal import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.internal.event.callAndRemoveIfRequired
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.utils.JavaFriendlyAPI import net.mamoe.mirai.utils.JavaFriendlyAPI
import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.MiraiExperimentalApi
@ -143,26 +144,32 @@ public interface CancellableEvent : Event {
* @see __broadcastJava Java 使用 * @see __broadcastJava Java 使用
*/ */
@JvmSynthetic @JvmSynthetic
public suspend fun <E : Event> E.broadcast(): E = apply { public suspend fun <E : Event> E.broadcast(): E {
check(this is AbstractEvent) { check(this is AbstractEvent) {
"Events must extend AbstractEvent" "Events must extend AbstractEvent"
} }
if (this is BroadcastControllable && !this.shouldBroadcast) { if (this is BroadcastControllable && !this.shouldBroadcast) {
return@apply return this
} }
this.broadCastLock.withLock { this.broadCastLock.withLock {
this._intercepted = false this._intercepted = false
if (EventDisabled) return@withLock if (EventDisabled) return@withLock
if (this is Packet.NoEventLog) return@withLock if (this is Packet.NoEventLog) return@withLock
if (this is Packet) return@withLock // all [Packet]s are logged in [LoggingPacketHandler] if (this is Packet.NoLog) return@withLock
if (this is MessageEvent) return@withLock // specially handled in [LoggingPacketHandlerAdapter]
// if (this is Packet) return@withLock // all [Packet]s are logged in [LoggingPacketHandlerAdapter]
if (this is BotEvent) { if (this is BotEvent) {
this.bot.logger.verbose { "Event: $this" } this.bot.logger.verbose { "Event: $this" }
} else { } else {
MiraiLogger.TopLevel.verbose { "Event: $this" } MiraiLogger.TopLevel.verbose { "Event: $this" }
} }
this.broadcastInternal() // inline, no extra cost
callAndRemoveIfRequired(this)
} }
return this
} }
/** /**

View File

@ -97,66 +97,53 @@ internal object GlobalEventListeners {
} }
// inline: NO extra Continuation internal suspend fun <E : AbstractEvent> callAndRemoveIfRequired(event: E) {
@Suppress("UNCHECKED_CAST")
internal suspend inline fun AbstractEvent.broadcastInternal() {
callAndRemoveIfRequired(this@broadcastInternal)
}
internal inline fun <E, T : Iterable<E>> T.forEach0(block: T.(E) -> Unit) {
forEach { block(it) }
}
@Suppress("DuplicatedCode")
internal suspend inline fun <E : AbstractEvent> callAndRemoveIfRequired(
event: E
) {
for (p in EventPriority.prioritiesExcludedMonitor) { for (p in EventPriority.prioritiesExcludedMonitor) {
GlobalEventListeners[p].forEach0 { registeredRegistry -> val container = GlobalEventListeners[p]
if (event.isIntercepted) { for (registry in container) {
return if (event.isIntercepted) return
} if (!registry.type.isInstance(event)) continue
if (!registeredRegistry.type.isInstance(event)) return@forEach0 val listener = registry.listener
val listener = registeredRegistry.listener process(container, registry, listener, event)
when (listener.concurrencyKind) { }
ConcurrencyKind.LOCKED -> { }
(listener as Handler).lock!!.withLock {
if (listener.onEvent(event) == ListeningStatus.STOPPED) { if (event.isIntercepted) return
remove(registeredRegistry) val container = GlobalEventListeners[EventPriority.MONITOR]
} when (container.size) {
} 0 -> return
} 1 -> {
ConcurrencyKind.CONCURRENT -> { val registry = container.firstOrNull() ?: return
if (listener.onEvent(event) == ListeningStatus.STOPPED) { if (!registry.type.isInstance(event)) return
remove(registeredRegistry) process(container, registry, registry.listener, event)
} }
} else -> supervisorScope {
for (registry in GlobalEventListeners[EventPriority.MONITOR]) {
if (!registry.type.isInstance(event)) continue
launch { process(container, registry, registry.listener, event) }
} }
} }
} }
coroutineScope { }
GlobalEventListeners[EventPriority.MONITOR].forEach0 { registeredRegistry ->
if (event.isIntercepted) { private suspend fun <E : AbstractEvent> process(
return@coroutineScope container: ConcurrentLinkedQueue<ListenerRegistry>,
} registry: ListenerRegistry,
if (!registeredRegistry.type.isInstance(event)) return@forEach0 listener: Listener<Event>,
val listener = registeredRegistry.listener event: E,
launch { ) {
when (listener.concurrencyKind) { when (listener.concurrencyKind) {
ConcurrencyKind.LOCKED -> { ConcurrencyKind.LOCKED -> {
(listener as Handler).lock!!.withLock { (listener as Handler).lock!!.withLock {
if (listener.onEvent(event) == ListeningStatus.STOPPED) { if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry) container.remove(registry)
}
}
}
ConcurrencyKind.CONCURRENT -> {
if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry)
}
}
} }
} }
} }
ConcurrencyKind.CONCURRENT -> {
if (listener.onEvent(event) == ListeningStatus.STOPPED) {
container.remove(registry)
}
}
} }
} }

View File

@ -27,7 +27,7 @@ import java.util.*
* *
* 示例: * 示例:
* ```log * ```log
* 2020-05-21 19:51:09 V/Bot 1994701021: Send: OidbSvc.0x88d_7 * 2020-05-21 19:51:09 V/Bot 123456789: Send: OidbSvc.0x88d_7
* ``` * ```
* *
* 日期时间格式为 `yyyy-MM-dd HH:mm:ss`, * 日期时间格式为 `yyyy-MM-dd HH:mm:ss`,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2020 Mamoe Technologies and contributors. * Copyright 2019-2021 Mamoe Technologies and contributors.
* *
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * 此源代码的使用受 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. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -234,7 +234,7 @@ public inline fun MiraiLogger.error(message: () -> String?, e: Throwable?) {
* *
* 示例: * 示例:
* ```log * ```log
* 2020-05-21 19:51:09 V/Bot 1994701021: Send: OidbSvc.0x88d_7 * 2020-05-21 19:51:09 V/Bot 123456789: Send: OidbSvc.0x88d_7
* ``` * ```
* *
* 日期时间格式为 `yyyy-MM-dd HH:mm:ss`, * 日期时间格式为 `yyyy-MM-dd HH:mm:ss`,

View File

@ -27,7 +27,7 @@ import java.util.*
* *
* 示例: * 示例:
* ```log * ```log
* 2020-05-21 19:51:09 V/Bot 1994701021: Send: OidbSvc.0x88d_7 * 2020-05-21 19:51:09 V/Bot 123456789: Send: OidbSvc.0x88d_7
* ``` * ```
* *
* 日期时间格式为 `yyyy-MM-dd HH:mm:ss`, * 日期时间格式为 `yyyy-MM-dd HH:mm:ss`,

View File

@ -163,9 +163,10 @@ internal open class QQAndroidBot constructor(
set(ContactUpdater, ContactUpdaterImpl(bot, components, networkLogger)) set(ContactUpdater, ContactUpdaterImpl(bot, components, networkLogger))
set(BdhSessionSyncer, BdhSessionSyncerImpl(configuration, networkLogger, components)) set(BdhSessionSyncer, BdhSessionSyncerImpl(configuration, networkLogger, components))
set(ServerList, ServerListImpl()) set(ServerList, ServerListImpl())
set(PacketLoggingStrategy, PacketLoggingStrategyImpl(bot))
set( set(
PacketHandler, PacketHandlerChain( PacketHandler, PacketHandlerChain(
LoggingPacketHandler(bot, networkLogger), LoggingPacketHandlerAdapter(networkLogger, get(PacketLoggingStrategy)),
EventBroadcasterPacketHandler(networkLogger), EventBroadcasterPacketHandler(networkLogger),
CallPacketFactoryPacketHandler(bot) CallPacketFactoryPacketHandler(bot)
) )

View File

@ -9,7 +9,7 @@
package net.mamoe.mirai.internal.network package net.mamoe.mirai.internal.network
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.AbstractBot
import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
@ -52,12 +52,12 @@ internal class ParseErrorPacket(
) : Packet, Packet.NoLog { ) : Packet, Packet.NoLog {
enum class Direction { enum class Direction {
TO_BOT_LOGGER { TO_BOT_LOGGER {
override fun getLogger(bot: QQAndroidBot): MiraiLogger = bot.logger override fun getLogger(bot: AbstractBot): MiraiLogger = bot.logger
}, },
TO_NETWORK_LOGGER { TO_NETWORK_LOGGER {
override fun getLogger(bot: QQAndroidBot): MiraiLogger = bot.network.logger override fun getLogger(bot: AbstractBot): MiraiLogger = bot.network.logger
}; };
abstract fun getLogger(bot: QQAndroidBot): MiraiLogger abstract fun getLogger(bot: AbstractBot): MiraiLogger
} }
} }

View File

@ -13,17 +13,13 @@ import net.mamoe.mirai.event.BroadcastControllable
import net.mamoe.mirai.event.CancellableEvent import net.mamoe.mirai.event.CancellableEvent
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.contact.logMessageReceived import net.mamoe.mirai.internal.network.MultiPacket
import net.mamoe.mirai.internal.contact.replaceMagicCodes
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.ParseErrorPacket
import net.mamoe.mirai.internal.network.component.ComponentKey import net.mamoe.mirai.internal.network.component.ComponentKey
import net.mamoe.mirai.internal.network.protocol.packet.* import net.mamoe.mirai.internal.network.protocol.packet.*
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.cast import net.mamoe.mirai.utils.cast
import net.mamoe.mirai.utils.verbose
internal interface PacketHandler { internal interface PacketHandler {
suspend fun handlePacket(incomingPacket: IncomingPacket) suspend fun handlePacket(incomingPacket: IncomingPacket)
@ -53,29 +49,15 @@ internal data class ExceptionInPacketHandlerException(
override val cause: Throwable, override val cause: Throwable,
) : IllegalStateException("Exception in PacketHandler '$packetHandler'.") ) : IllegalStateException("Exception in PacketHandler '$packetHandler'.")
internal class LoggingPacketHandler( internal class LoggingPacketHandlerAdapter(
private val bot: QQAndroidBot,
private val logger: MiraiLogger, private val logger: MiraiLogger,
private val strategy: PacketLoggingStrategy,
) : PacketHandler { ) : PacketHandler {
override suspend fun handlePacket(incomingPacket: IncomingPacket) { override suspend fun handlePacket(incomingPacket: IncomingPacket) {
val packet = incomingPacket.data ?: return strategy.logReceived(logger, incomingPacket)
if (!bot.logger.isEnabled && !logger.isEnabled) return
when {
packet is ParseErrorPacket -> {
packet.direction.getLogger(bot).error(packet.error)
}
packet is MessageEvent -> packet.logMessageReceived()
packet is Packet.NoLog -> {
// nothing to do
}
packet is Event && packet !is Packet.NoEventLog -> bot.logger.verbose {
"Event: $packet".replaceMagicCodes()
}
else -> logger.verbose { "Recv: ${incomingPacket.commandName} ${incomingPacket.data}".replaceMagicCodes() }
}
} }
override fun toString(): String = "LoggingPacketHandler" override fun toString(): String = "LoggingPacketHandlerAdapter"
} }
internal class EventBroadcasterPacketHandler( internal class EventBroadcasterPacketHandler(
@ -83,7 +65,16 @@ internal class EventBroadcasterPacketHandler(
) : PacketHandler { ) : PacketHandler {
override suspend fun handlePacket(incomingPacket: IncomingPacket) { override suspend fun handlePacket(incomingPacket: IncomingPacket) {
val packet = incomingPacket.data ?: return val data = incomingPacket.data ?: return
impl(data)
}
private suspend fun impl(packet: Packet) {
if (packet is MultiPacket<*>) {
for (p in packet) {
impl(p)
}
}
when { when {
packet is CancellableEvent && packet.isCancelled -> return packet is CancellableEvent && packet.isCancelled -> return
packet is BroadcastControllable && !packet.shouldBroadcast -> return packet is BroadcastControllable && !packet.shouldBroadcast -> return
@ -105,7 +96,7 @@ internal class EventBroadcasterPacketHandler(
return qualified.substringAfter("net.mamoe.mirai.event.events.") return qualified.substringAfter("net.mamoe.mirai.event.events.")
} }
override fun toString(): String = "LoggingPacketHandler" override fun toString(): String = "EventBroadcasterPacketHandler"
} }
internal class CallPacketFactoryPacketHandler( internal class CallPacketFactoryPacketHandler(

View File

@ -0,0 +1,80 @@
/*
* 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.components
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.internal.AbstractBot
import net.mamoe.mirai.internal.contact.logMessageReceived
import net.mamoe.mirai.internal.contact.replaceMagicCodes
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.ParseErrorPacket
import net.mamoe.mirai.internal.network.component.ComponentKey
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.systemProp
import net.mamoe.mirai.utils.verbose
/**
* Implementation must be fast and non-blocking, throwing no exception.
*/
internal interface PacketLoggingStrategy {
fun logSent(logger: MiraiLogger, outgoingPacket: OutgoingPacket)
fun logReceived(logger: MiraiLogger, incomingPacket: IncomingPacket)
companion object : ComponentKey<PacketLoggingStrategy>
}
internal class PacketLoggingStrategyImpl(
private val bot: AbstractBot,
private val blacklist: Set<String> = DEFAULT_BLACKLIST,
) : PacketLoggingStrategy {
override fun logSent(logger: MiraiLogger, outgoingPacket: OutgoingPacket) {
if (outgoingPacket.commandName in blacklist) return
logger.verbose { "Send: ${outgoingPacket.commandName}" }
}
override fun logReceived(logger: MiraiLogger, incomingPacket: IncomingPacket) {
val packet = incomingPacket.data ?: return
if (!bot.logger.isEnabled && !logger.isEnabled) return
when {
packet is ParseErrorPacket -> {
packet.direction.getLogger(bot).error(packet.error)
}
packet is MessageEvent -> packet.logMessageReceived()
packet is Packet.NoLog -> {
// nothing to do
}
packet is Event && packet !is Packet.NoEventLog -> bot.logger.verbose {
"Event: $packet".replaceMagicCodes()
}
else -> {
if (SHOW_PACKET_DETAILS) {
logger.verbose { "Recv: ${incomingPacket.commandName} ${incomingPacket.data}".replaceMagicCodes() }
} else {
logger.verbose { "Recv: ${incomingPacket.commandName}".replaceMagicCodes() }
}
}
}
}
companion object {
@JvmField
val DEFAULT_BLACKLIST = setOf(
"MessageSvc.PbDeleteMsg",
"MessageSvc.PbGetMsg", // they are too verbose.
"OnlinePush.RespPush"
)
@JvmField
var SHOW_PACKET_DETAILS = systemProp("mirai.debug.network.show.packet.details", false)
}
}

View File

@ -9,6 +9,7 @@
package net.mamoe.mirai.internal.network.handler package net.mamoe.mirai.internal.network.handler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.selects.SelectClause1 import kotlinx.coroutines.selects.SelectClause1
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
@ -30,7 +31,7 @@ import net.mamoe.mirai.utils.MiraiLogger
* @see NetworkHandlerSupport * @see NetworkHandlerSupport
* @see NetworkHandlerFactory * @see NetworkHandlerFactory
*/ */
internal interface NetworkHandler { internal interface NetworkHandler : CoroutineScope {
val context: NetworkHandlerContext val context: NetworkHandlerContext
fun isOk() = state == State.OK fun isOk() = state == State.OK

View File

@ -14,6 +14,7 @@ import kotlinx.coroutines.selects.SelectClause1
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.components.PacketCodec import net.mamoe.mirai.internal.network.components.PacketCodec
import net.mamoe.mirai.internal.network.components.PacketHandler import net.mamoe.mirai.internal.network.components.PacketHandler
import net.mamoe.mirai.internal.network.components.PacketLoggingStrategy
import net.mamoe.mirai.internal.network.components.RawIncomingPacket import net.mamoe.mirai.internal.network.components.RawIncomingPacket
import net.mamoe.mirai.internal.network.handler.state.StateObserver import net.mamoe.mirai.internal.network.handler.state.StateObserver
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
@ -69,7 +70,7 @@ internal abstract class NetworkHandlerSupport(
val listener = PacketListener(packet.commandName, packet.sequenceId) val listener = PacketListener(packet.commandName, packet.sequenceId)
var exception: Throwable? = null var exception: Throwable? = null
repeat(attempts.coerceAtLeast(1)) { repeat(attempts.coerceAtLeast(1)) {
logger.verbose { "Send: ${packet.commandName}" } context[PacketLoggingStrategy].logSent(logger, packet)
try { try {
packetListeners.add(listener) packetListeners.add(listener)
sendPacketImpl(packet) sendPacketImpl(packet)
@ -92,7 +93,7 @@ internal abstract class NetworkHandlerSupport(
} }
final override suspend fun sendWithoutExpect(packet: OutgoingPacket) { final override suspend fun sendWithoutExpect(packet: OutgoingPacket) {
logger.verbose { "Send: ${packet.commandName}" } context[PacketLoggingStrategy].logSent(logger, packet)
sendPacketImpl(packet) sendPacketImpl(packet)
} }
@ -102,7 +103,7 @@ internal abstract class NetworkHandlerSupport(
// } else { // } else {
// logger.info { "NetworkHandler '$this' closed: $cause" } // logger.info { "NetworkHandler '$this' closed: $cause" }
// } // }
coroutineContext.job.cancel("NetworkHandler closed.", cause) coroutineContext.job.cancel("NetworkHandler closed", cause)
} }
protected val packetLogger: MiraiLogger by lazy { protected val packetLogger: MiraiLogger by lazy {

View File

@ -18,6 +18,7 @@ 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.NetworkHandlerContext import net.mamoe.mirai.internal.network.handler.NetworkHandlerContext
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import kotlin.coroutines.CoroutineContext
/** /**
* A proxy to [NetworkHandler] that delegates calls to instance returned by [NetworkHandlerSelector.awaitResumeInstance]. * A proxy to [NetworkHandler] that delegates calls to instance returned by [NetworkHandlerSelector.awaitResumeInstance].
@ -52,6 +53,9 @@ internal class SelectorNetworkHandler(
selector.getResumedInstance()?.close(cause) selector.getResumedInstance()?.close(cause)
} }
override val coroutineContext: CoroutineContext
get() = selector.getResumedInstance()?.coroutineContext ?: scope.coroutineContext // merely use fallback
override fun toString(): String = "SelectorNetworkHandler(currentInstance=${selector.getResumedInstance()})" override fun toString(): String = "SelectorNetworkHandler(currentInstance=${selector.getResumedInstance()})"
} }

View File

@ -81,7 +81,7 @@ internal open class NettyNetworkHandler(
private inner class OutgoingPacketEncoder : MessageToByteEncoder<OutgoingPacket>(OutgoingPacket::class.java) { private inner class OutgoingPacketEncoder : MessageToByteEncoder<OutgoingPacket>(OutgoingPacket::class.java) {
override fun encode(ctx: ChannelHandlerContext, msg: OutgoingPacket, out: ByteBuf) { override fun encode(ctx: ChannelHandlerContext, msg: OutgoingPacket, out: ByteBuf) {
PacketCodec.PacketLogger.debug { "encode: $msg" } packetLogger.debug { "encode: $msg" }
out.writeBytes(msg.delegate) out.writeBytes(msg.delegate)
} }
} }
@ -261,19 +261,29 @@ internal open class NettyNetworkHandler(
connection.writeAndFlush(packet) connection.writeAndFlush(packet)
} }
private val configPush = this@NettyNetworkHandler.launch(CoroutineName("ConfigPush sync")) {
try {
context[ConfigPushProcessor].syncConfigPush(this@NettyNetworkHandler)
} catch (e: ConfigPushProcessor.RequireReconnectException) {
setState { StateConnecting(ExceptionCollector(e), false) }
}
}
override suspend fun resumeConnection0() { override suspend fun resumeConnection0() {
(coroutineContext.job as CompletableJob).run { (coroutineContext.job as CompletableJob).run {
complete() complete()
join() join()
} }
setState { StateOK(connection) } joinCompleted(configPush) // throw exception
setState { StateOK(connection, configPush) }
} // noop } // noop
override fun toString(): String = "StateLoading" override fun toString(): String = "StateLoading"
} }
protected inner class StateOK( protected inner class StateOK(
private val connection: NettyChannel private val connection: NettyChannel,
private val configPush: Job,
) : NettyState(State.OK) { ) : NettyState(State.OK) {
init { init {
coroutineContext.job.invokeOnCompletion { coroutineContext.job.invokeOnCompletion {
@ -307,14 +317,6 @@ internal open class NettyNetworkHandler(
} }
} }
private val configPush = launch(CoroutineName("ConfigPush sync")) {
try {
context[ConfigPushProcessor].syncConfigPush(this@NettyNetworkHandler)
} catch (e: ConfigPushProcessor.RequireReconnectException) {
setState { StateClosed(e) }
}
}
// we can also move them as observers if needed. // we can also move them as observers if needed.
private val keyRefresh = launch(CoroutineName("Key refresh")) { private val keyRefresh = launch(CoroutineName("Key refresh")) {
@ -332,10 +334,6 @@ internal open class NettyNetworkHandler(
joinCompleted(keyRefresh) joinCompleted(keyRefresh)
} // noop } // noop
private suspend inline fun joinCompleted(job: Job) {
if (job.isCompleted) job.join()
}
override fun toString(): String = "StateOK" override fun toString(): String = "StateOK"
} }

View File

@ -14,6 +14,7 @@ import io.netty.buffer.ByteBufInputStream
import io.netty.channel.ChannelFuture import io.netty.channel.ChannelFuture
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.Job
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.SimpleLogger import net.mamoe.mirai.utils.SimpleLogger
@ -55,3 +56,8 @@ internal fun MiraiLogger.asCoroutineExceptionHandler(
) )
} }
} }
internal suspend inline fun joinCompleted(job: Job) {
if (job.isCompleted) job.join()
}

View File

@ -18,6 +18,7 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.io.core.* import kotlinx.io.core.*
import net.mamoe.mirai.Bot
import net.mamoe.mirai.Mirai import net.mamoe.mirai.Mirai
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
@ -55,7 +56,10 @@ import net.mamoe.mirai.message.data.MessageSourceKind.STRANGER
import net.mamoe.mirai.message.data.MessageSourceKind.TEMP import net.mamoe.mirai.message.data.MessageSourceKind.TEMP
import net.mamoe.mirai.message.data.PlainText import net.mamoe.mirai.message.data.PlainText
import net.mamoe.mirai.message.data.buildMessageChain import net.mamoe.mirai.message.data.buildMessageChain
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.cast
import net.mamoe.mirai.utils.debug
import net.mamoe.mirai.utils.read
import net.mamoe.mirai.utils.toUHexString
import kotlin.random.Random import kotlin.random.Random
@ -93,12 +97,13 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
) )
} }
open class GetMsgSuccess(delegate: List<Packet>, syncCookie: ByteArray?, val bot: QQAndroidBot) : Response( open class GetMsgSuccess(delegate: List<Packet>, syncCookie: ByteArray?, bot: QQAndroidBot) : Response(
MsgSvc.SyncFlag.STOP, delegate, MsgSvc.SyncFlag.STOP, delegate,
syncCookie syncCookie,
bot
), Event, ), Event,
Packet.NoLog { Packet.NoLog {
override fun toString(): String = "MessageSvcPbGetMsg.GetMsgSuccess(messages=<Iterable>))" override fun toString(): String = "MessageSvcPbGetMsg.GetMsgSuccess"
} }
/** /**
@ -107,15 +112,16 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
open class Response( open class Response(
internal val syncFlagFromServer: MsgSvc.SyncFlag, internal val syncFlagFromServer: MsgSvc.SyncFlag,
delegate: List<Packet>, delegate: List<Packet>,
val syncCookie: ByteArray? val syncCookie: ByteArray?, override val bot: Bot
) : ) :
AbstractEvent(), AbstractEvent(),
MultiPacket<Packet>, MultiPacket<Packet>,
Iterable<Packet> by (delegate), Iterable<Packet> by (delegate),
Packet.NoLog { Packet.NoLog,
BotEvent {
override fun toString(): String = override fun toString(): String =
"MessageSvcPbGetMsg.Response(syncFlagFromServer=$syncFlagFromServer, messages=<Iterable>))" "MessageSvcPbGetMsg.Response(flag=$syncFlagFromServer)"
} }
class EmptyResponse( class EmptyResponse(
@ -128,9 +134,12 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
val resp = readProtoBuf(MsgSvc.PbGetMsgResp.serializer()) val resp = readProtoBuf(MsgSvc.PbGetMsgResp.serializer())
if (resp.result != 0) { if (resp.result != 0) {
bot.network.logger // this is normally recoverable, no need to log
.warning { "MessageSvcPushNotify: result != 0, result = ${resp.result}, errorMsg=${resp.errmsg}" }
bot.launch(CoroutineName("MessageSvcPushNotify.retry")) {
// bot.network.logger
// .warning { "MessageSvcPushNotify: result != 0, result = ${resp.result}, errorMsg=${resp.errmsg}" }
bot.network.launch(CoroutineName("MessageSvcPushNotify.retry")) {
delay(500 + Random.nextLong(0, 1000)) delay(500 + Random.nextLong(0, 1000))
bot.network.run { bot.network.run {
MessageSvcPbGetMsg(bot.client, syncCookie = null).sendWithoutExpect() MessageSvcPbGetMsg(bot.client, syncCookie = null).sendWithoutExpect()
@ -188,7 +197,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
if (resp.syncFlag == MsgSvc.SyncFlag.STOP) { if (resp.syncFlag == MsgSvc.SyncFlag.STOP) {
return GetMsgSuccess(list, resp.syncCookie, bot) return GetMsgSuccess(list, resp.syncCookie, bot)
} }
return Response(resp.syncFlag, list, resp.syncCookie) return Response(resp.syncFlag, list, resp.syncCookie, bot)
} }
override suspend fun QQAndroidBot.handle(packet: Response) { override suspend fun QQAndroidBot.handle(packet: Response) {

View File

@ -110,7 +110,8 @@ internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abs
set(ContactUpdater, ContactUpdaterImpl(bot, components, networkLogger)) set(ContactUpdater, ContactUpdaterImpl(bot, components, networkLogger))
set(BdhSessionSyncer, BdhSessionSyncerImpl(configuration, networkLogger, components)) set(BdhSessionSyncer, BdhSessionSyncerImpl(configuration, networkLogger, components))
set(ServerList, ServerListImpl()) set(ServerList, ServerListImpl())
set(PacketHandler, LoggingPacketHandler(bot, networkLogger)) set(PacketLoggingStrategy, PacketLoggingStrategyImpl(bot))
set(PacketHandler, LoggingPacketHandlerAdapter(networkLogger, get(PacketLoggingStrategy)))
set(PacketCodec, PacketCodecImpl()) set(PacketCodec, PacketCodecImpl())
set(OtherClientUpdater, OtherClientUpdaterImpl(bot, components, bot.logger)) set(OtherClientUpdater, OtherClientUpdaterImpl(bot, components, bot.logger))
set(ConfigPushSyncer, ConfigPushSyncerImpl()) set(ConfigPushSyncer, ConfigPushSyncerImpl())