Commit 7820b43f authored by Him188's avatar Him188

Review: ensure reentrant, rearrange coroutine job management

parent 789317fb
...@@ -180,6 +180,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -180,6 +180,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
// caches // caches
private val _pendingEnabled = atomic(true) private val _pendingEnabled = atomic(true)
internal val pendingEnabled get() = _pendingEnabled.value internal val pendingEnabled get() = _pendingEnabled.value
@Volatile
internal var pendingIncomingPackets: LockFreeLinkedList<KnownPacketFactories.IncomingPacket<*>>? = internal var pendingIncomingPackets: LockFreeLinkedList<KnownPacketFactories.IncomingPacket<*>>? =
LockFreeLinkedList() LockFreeLinkedList()
...@@ -191,119 +192,124 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -191,119 +192,124 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
bot.friends.delegate.clear() bot.friends.delegate.clear()
bot.groups.delegate.clear() bot.groups.delegate.clear()
val friendListJob = launch { if (!pendingEnabled) {
lateinit var loadFriends: suspend () -> Unit pendingIncomingPackets = LockFreeLinkedList()
// 不要用 fun, 不要 join declaration, 不要用 val, 编译失败警告 _pendingEnabled.value = true
loadFriends = suspend loadFriends@{ }
logger.info("开始加载好友信息")
var currentFriendCount = 0 coroutineScope {
var totalFriendCount: Short launch {
while (true) { lateinit var loadFriends: suspend () -> Unit
val data = runCatching { // 不要用 fun, 不要 join declaration, 不要用 val, 编译失败警告
FriendList.GetFriendGroupList( loadFriends = suspend loadFriends@{
bot.client, logger.info("开始加载好友信息")
currentFriendCount, var currentFriendCount = 0
150, var totalFriendCount: Short
0, while (true) {
0 val data = runCatching {
).sendAndExpect<FriendList.GetFriendGroupList.Response>(timeoutMillis = 5000, retry = 2) FriendList.GetFriendGroupList(
}.getOrElse { bot.client,
logger.error("无法加载好友列表", it) currentFriendCount,
this@QQAndroidBotNetworkHandler.launch { delay(10.secondsToMillis); loadFriends() } 150,
logger.error("稍后重试加载好友列表") 0,
return@loadFriends 0
} ).sendAndExpect<FriendList.GetFriendGroupList.Response>(timeoutMillis = 5000, retry = 2)
totalFriendCount = data.totalFriendCount }.getOrElse {
data.friendList.forEach { logger.error("无法加载好友列表", it)
// atomic add this@QQAndroidBotNetworkHandler.launch { delay(10.secondsToMillis); loadFriends() }
bot.friends.delegate.addLast( logger.error("稍后重试加载好友列表")
QQImpl( return@loadFriends
bot,
bot.coroutineContext,
it.friendUin,
FriendInfoImpl(it)
)
).also {
currentFriendCount++
} }
totalFriendCount = data.totalFriendCount
data.friendList.forEach {
// atomic add
bot.friends.delegate.addLast(
QQImpl(
bot,
bot.coroutineContext,
it.friendUin,
FriendInfoImpl(it)
)
).also {
currentFriendCount++
}
}
logger.verbose { "正在加载好友列表 ${currentFriendCount}/${totalFriendCount}" }
if (currentFriendCount >= totalFriendCount) {
break
}
// delay(200)
} }
logger.verbose { "正在加载好友列表 ${currentFriendCount}/${totalFriendCount}" } logger.info { "好友列表加载完成, 共 ${currentFriendCount}个" }
if (currentFriendCount >= totalFriendCount) {
break
}
// delay(200)
} }
logger.info { "好友列表加载完成, 共 ${currentFriendCount}个" }
}
loadFriends() loadFriends()
} }
val groupJob = launch { launch {
try { try {
logger.info("开始加载群组列表与群成员列表") logger.info("开始加载群组列表与群成员列表")
val troopListData = FriendList.GetTroopListSimplify(bot.client) val troopListData = FriendList.GetTroopListSimplify(bot.client)
.sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 2) .sendAndExpect<FriendList.GetTroopListSimplify.Response>(retry = 2)
troopListData.groups.forEach { troopNum -> troopListData.groups.forEach { troopNum ->
// 别用 fun, 别 val, 编译失败警告 // 别用 fun, 别 val, 编译失败警告
lateinit var loadGroup: suspend () -> Unit lateinit var loadGroup: suspend () -> Unit
loadGroup = suspend { loadGroup = suspend {
tryNTimesOrException(3) { tryNTimesOrException(3) {
bot.groups.delegate.addLast( bot.groups.delegate.addLast(
@Suppress("DuplicatedCode") @Suppress("DuplicatedCode")
(GroupImpl( (GroupImpl(
bot = bot, bot = bot,
coroutineContext = bot.coroutineContext, coroutineContext = bot.coroutineContext,
id = troopNum.groupCode, id = troopNum.groupCode,
groupInfo = bot._lowLevelQueryGroupInfo(troopNum.groupCode).apply { groupInfo = bot._lowLevelQueryGroupInfo(troopNum.groupCode).apply {
this as GroupInfoImpl this as GroupInfoImpl
if (this.delegate.groupName == null) { if (this.delegate.groupName == null) {
this.delegate.groupName = troopNum.groupName this.delegate.groupName = troopNum.groupName
} }
if (this.delegate.groupMemo == null) { if (this.delegate.groupMemo == null) {
this.delegate.groupMemo = troopNum.groupMemo this.delegate.groupMemo = troopNum.groupMemo
} }
if (this.delegate.groupUin == null) { if (this.delegate.groupUin == null) {
this.delegate.groupUin = troopNum.groupUin this.delegate.groupUin = troopNum.groupUin
} }
this.delegate.groupCode = troopNum.groupCode this.delegate.groupCode = troopNum.groupCode
}, },
members = bot._lowLevelQueryGroupMemberList( members = bot._lowLevelQueryGroupMemberList(
troopNum.groupUin, troopNum.groupUin,
troopNum.groupCode, troopNum.groupCode,
troopNum.dwGroupOwnerUin troopNum.dwGroupOwnerUin
) )
)) ))
) )
}?.let { }?.let {
logger.error { "群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试" } logger.error { "群${troopNum.groupCode}的列表拉取失败, 一段时间后将会重试" }
logger.error(it) logger.error(it)
this@QQAndroidBotNetworkHandler.launch { this@QQAndroidBotNetworkHandler.launch {
delay(10_000) delay(10_000)
loadGroup() loadGroup()
}
} }
Unit // 别删, 编译失败警告
}
launch {
loadGroup()
} }
Unit // 别删, 编译失败警告
}
launch {
loadGroup()
} }
logger.info { "群组列表与群成员加载完成, 共 ${troopListData.groups.size}个" }
} catch (e: Exception) {
logger.error { "加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表" }
logger.error(e)
} }
logger.info { "群组列表与群成员加载完成, 共 ${troopListData.groups.size}个" }
} catch (e: Exception) {
logger.error { "加载组信息失败|一般这是由于加载过于频繁导致/将以热加载方式加载群列表" }
logger.error(e)
} }
} }
joinAll(friendListJob, groupJob)
withTimeoutOrNull(5000) { withTimeoutOrNull(5000) {
lateinit var listener: Listener<PacketReceivedEvent> lateinit var listener: Listener<PacketReceivedEvent>
listener = this.subscribeAlways { listener = this.subscribeAlways {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment