mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-31 03:30:08 +08:00
Adjust job cancelling hence fix #65
This commit is contained in:
parent
0643e9eac9
commit
b2e0114e4f
@ -78,7 +78,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
} catch (e: CancellationException) {
|
} catch (e: CancellationException) {
|
||||||
return@launch
|
return@launch
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
BotOfflineEvent.Dropped(bot).broadcast()
|
if (this@QQAndroidBotNetworkHandler.isActive) {
|
||||||
|
BotOfflineEvent.Dropped(bot).broadcast()
|
||||||
|
}
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
packetReceiveLock.withLock {
|
packetReceiveLock.withLock {
|
||||||
@ -185,6 +187,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
|
|
||||||
@UseExperimental(MiraiExperimentalAPI::class, ExperimentalTime::class)
|
@UseExperimental(MiraiExperimentalAPI::class, ExperimentalTime::class)
|
||||||
override suspend fun init(): Unit = coroutineScope {
|
override suspend fun init(): Unit = coroutineScope {
|
||||||
|
check(bot.isActive) { "bot is dead therefore network can't init" }
|
||||||
|
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't init" }
|
||||||
MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendWithoutExpect()
|
MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendWithoutExpect()
|
||||||
|
|
||||||
bot.qqs.delegate.clear()
|
bot.qqs.delegate.clear()
|
||||||
@ -494,6 +498,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
* 发送一个包, 但不期待任何返回.
|
* 发送一个包, 但不期待任何返回.
|
||||||
*/
|
*/
|
||||||
suspend fun OutgoingPacket.sendWithoutExpect() {
|
suspend fun OutgoingPacket.sendWithoutExpect() {
|
||||||
|
check(bot.isActive) { "bot is dead therefore can't send any packet" }
|
||||||
|
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't send any packet" }
|
||||||
logger.info("Send: ${this.commandName}")
|
logger.info("Send: ${this.commandName}")
|
||||||
withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
|
withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
|
||||||
channel.send(delegate)
|
channel.send(delegate)
|
||||||
@ -509,6 +515,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
require(timeoutMillis > 0) { "timeoutMillis must > 0" }
|
require(timeoutMillis > 0) { "timeoutMillis must > 0" }
|
||||||
require(retry >= 0) { "retry must >= 0" }
|
require(retry >= 0) { "retry must >= 0" }
|
||||||
|
|
||||||
|
check(bot.isActive) { "bot is dead therefore can't send any packet" }
|
||||||
|
check(this@QQAndroidBotNetworkHandler.isActive) { "network is dead therefore can't send any packet" }
|
||||||
|
|
||||||
var lastException: Exception? = null
|
var lastException: Exception? = null
|
||||||
if (retry == 0) {
|
if (retry == 0) {
|
||||||
val handler = PacketListener(commandName = commandName, sequenceId = sequenceId)
|
val handler = PacketListener(commandName = commandName, sequenceId = sequenceId)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused", "FunctionName", "NOTHING_TO_INLINE")
|
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused", "FunctionName", "NOTHING_TO_INLINE", "UnusedImport")
|
||||||
|
|
||||||
package net.mamoe.mirai
|
package net.mamoe.mirai
|
||||||
|
|
||||||
@ -35,7 +35,8 @@ import kotlin.jvm.JvmStatic
|
|||||||
*
|
*
|
||||||
* 注: Bot 为全协程实现, 没有其他任务时若不使用 [join], 主线程将会退出.
|
* 注: Bot 为全协程实现, 没有其他任务时若不使用 [join], 主线程将会退出.
|
||||||
*
|
*
|
||||||
* @see Contact
|
* @see Contact 联系人
|
||||||
|
* @see kotlinx.coroutines.isActive 判断 [Bot] 是否正常运行中. (在线, 且没有被 [close])
|
||||||
*/
|
*/
|
||||||
@UseExperimental(MiraiInternalAPI::class)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
abstract class Bot : CoroutineScope {
|
abstract class Bot : CoroutineScope {
|
||||||
@ -195,7 +196,9 @@ abstract class Bot : CoroutineScope {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录, 或重新登录.
|
* 登录, 或重新登录.
|
||||||
* 重新登录时不会再次拉取联系人列表.
|
* 这个函数总是关闭一切现有网路任务, 然后重新登录并重新缓存好友列表和群列表.
|
||||||
|
*
|
||||||
|
* 一般情况下不需要重新登录. Mirai 能够自动处理掉线情况.
|
||||||
*
|
*
|
||||||
* 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.relogin]
|
* 最终调用 [net.mamoe.mirai.network.BotNetworkHandler.relogin]
|
||||||
*
|
*
|
||||||
@ -231,24 +234,19 @@ abstract class Bot : CoroutineScope {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭这个 [Bot], 停止一切相关活动. 所有引用都会被释放.
|
* 关闭这个 [Bot], 立即取消 [Bot] 的 [kotlinx.coroutines.SupervisorJob].
|
||||||
|
* 之后 [kotlinx.coroutines.isActive] 将会返回 `false`.
|
||||||
*
|
*
|
||||||
* 注: 不可重新登录. 必须重新实例化一个 [Bot].
|
* **注意:** 不可重新登录. 必须重新实例化一个 [Bot].
|
||||||
*
|
*
|
||||||
* @param cause 原因. 为 null 时视为正常关闭, 非 null 时视为异常关闭
|
* @param cause 原因. 为 null 时视为正常关闭, 非 null 时视为异常关闭
|
||||||
*
|
*
|
||||||
* @see closeAndJoin
|
* @see closeAndJoin 取消并 [Bot.join], 以确保 [Bot] 相关的活动被完全关闭
|
||||||
*/
|
*/
|
||||||
abstract fun close(cause: Throwable? = null)
|
abstract fun close(cause: Throwable? = null)
|
||||||
|
|
||||||
// region extensions
|
// region extensions
|
||||||
|
|
||||||
@Deprecated(message = "这个函数有歧义, 将在不久后删除", replaceWith = ReplaceWith("getFriend(this.toLong())"))
|
|
||||||
fun Int.qq(): QQ = getFriend(this.toLong())
|
|
||||||
|
|
||||||
@Deprecated(message = "这个函数有歧义, 将在不久后删除", replaceWith = ReplaceWith("getFriend(this)"))
|
|
||||||
fun Long.qq(): QQ = getFriend(this)
|
|
||||||
|
|
||||||
final override fun toString(): String {
|
final override fun toString(): String {
|
||||||
return "Bot(${uin})"
|
return "Bot(${uin})"
|
||||||
}
|
}
|
||||||
|
@ -89,22 +89,17 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
|
|||||||
private val offlineListener: Listener<BotOfflineEvent> = this.subscribeAlways { event ->
|
private val offlineListener: Listener<BotOfflineEvent> = this.subscribeAlways { event ->
|
||||||
when (event) {
|
when (event) {
|
||||||
is BotOfflineEvent.Dropped -> {
|
is BotOfflineEvent.Dropped -> {
|
||||||
|
if (!_network.isActive) {
|
||||||
|
return@subscribeAlways
|
||||||
|
}
|
||||||
bot.logger.info("Connection dropped or lost by server, retrying login")
|
bot.logger.info("Connection dropped or lost by server, retrying login")
|
||||||
|
|
||||||
var lastFailedException: Throwable? = null
|
tryNTimesOrException(configuration.reconnectionRetryTimes) {
|
||||||
repeat(configuration.reconnectionRetryTimes) {
|
delay(configuration.reconnectPeriodMillis)
|
||||||
try {
|
network.relogin()
|
||||||
network.relogin()
|
logger.info("Reconnected successfully")
|
||||||
logger.info("Reconnected successfully")
|
return@subscribeAlways
|
||||||
return@subscribeAlways
|
}?.let { throw it }
|
||||||
} catch (e: Throwable) {
|
|
||||||
lastFailedException = e
|
|
||||||
delay(configuration.reconnectPeriodMillis)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lastFailedException != null) {
|
|
||||||
throw lastFailedException!!
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is BotOfflineEvent.Active -> {
|
is BotOfflineEvent.Active -> {
|
||||||
val msg = if (event.cause == null) {
|
val msg = if (event.cause == null) {
|
||||||
@ -112,12 +107,12 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
|
|||||||
} else {
|
} else {
|
||||||
" with exception: " + event.cause.message
|
" with exception: " + event.cause.message
|
||||||
}
|
}
|
||||||
bot.logger.info("Bot is closed manually$msg")
|
bot.logger.info { "Bot is closed manually$msg" }
|
||||||
close(CancellationException(event.toString()))
|
closeAndJoin(CancellationException(event.toString()))
|
||||||
}
|
}
|
||||||
is BotOfflineEvent.Force -> {
|
is BotOfflineEvent.Force -> {
|
||||||
bot.logger.info("Connection occupied by another android device: ${event.message}")
|
bot.logger.info { "Connection occupied by another android device: ${event.message}" }
|
||||||
close(ForceOfflineException(event.toString()))
|
closeAndJoin(ForceOfflineException(event.toString()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,15 +171,19 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
|
|||||||
|
|
||||||
@UseExperimental(MiraiInternalAPI::class)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
override fun close(cause: Throwable?) {
|
override fun close(cause: Throwable?) {
|
||||||
|
if (!this.botJob.isActive) {
|
||||||
|
// already cancelled
|
||||||
|
return
|
||||||
|
}
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
if (cause == null) {
|
if (cause == null) {
|
||||||
|
this.botJob.cancel()
|
||||||
network.close()
|
network.close()
|
||||||
this.botJob.complete()
|
offlineListener.cancel()
|
||||||
offlineListener.complete()
|
|
||||||
} else {
|
} else {
|
||||||
|
this.botJob.cancel(CancellationException("bot cancelled", cause))
|
||||||
network.close(cause)
|
network.close(cause)
|
||||||
this.botJob.completeExceptionally(cause)
|
offlineListener.cancel(CancellationException("bot cancelled", cause))
|
||||||
offlineListener.completeExceptionally(cause)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
groups.delegate.clear()
|
groups.delegate.clear()
|
||||||
|
Loading…
Reference in New Issue
Block a user