Http api automatic release AuthSession

This commit is contained in:
ryoii 2020-02-26 00:34:03 +08:00
parent a1e262ce9b
commit c17361242b
3 changed files with 31 additions and 13 deletions

View File

@ -116,7 +116,8 @@ fun main() {
```
使用此方式释放session及其相关资源Bot不会被释放
**不使用的Session应当被释放否则Session持续保存Bot收到的消息将会导致内存泄露**
**不使用的Session应当被释放否则Session持续保存Bot收到的消息**
**长时间30分钟未被使用的Session会被系统自动释放以避免内存泄露**
#### 请求:

View File

@ -15,8 +15,7 @@ import net.mamoe.mirai.api.http.queue.MessageQueue
import net.mamoe.mirai.event.Listener
import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.event.subscribeMessages
import net.mamoe.mirai.message.MessagePacket
import net.mamoe.mirai.utils.currentTimeSeconds
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
@ -57,7 +56,13 @@ internal object SessionManager {
}
}
operator fun get(sessionKey: String) = allSession[sessionKey]
fun createAuthedSession(bot: Bot, originKey: String): AuthedSession = AuthedSession(bot, originKey, EmptyCoroutineContext).also { session ->
closeSession(originKey)
allSession[originKey] = session
}
operator fun get(sessionKey: String) = allSession[sessionKey]?.also {
if (it is AuthedSession) it.latestUsed = currentTimeSeconds }
fun containSession(sessionKey: String): Boolean = allSession.containsKey(sessionKey)
@ -76,14 +81,12 @@ internal object SessionManager {
* 需使用[SessionManager]
*/
abstract class Session internal constructor(
coroutineContext: CoroutineContext
coroutineContext: CoroutineContext,
val key: String = generateSessionKey()
) : CoroutineScope {
val supervisorJob = SupervisorJob(coroutineContext[Job])
final override val coroutineContext: CoroutineContext = supervisorJob + coroutineContext
val key: String = generateSessionKey()
internal open fun close() {
supervisorJob.complete()
}
@ -101,16 +104,33 @@ class TempSession internal constructor(coroutineContext: CoroutineContext) : Ses
* 任何[TempSession]认证后转化为一个[AuthedSession]
* 在这一步[AuthedSession]应该已经有assigned的bot
*/
class AuthedSession internal constructor(val bot: Bot, coroutineContext: CoroutineContext) : Session(coroutineContext) {
class AuthedSession internal constructor(val bot: Bot, originKey: String, coroutineContext: CoroutineContext) : Session(coroutineContext, originKey) {
companion object {
const val CHECK_TIME = 1800L // 1800s aka 30min
}
val messageQueue = MessageQueue()
private val _listener: Listener<BotEvent>
private val releaseJob: Job //手动释放将会在下一次检查时回收Session
internal var latestUsed = currentTimeSeconds
init {
_listener = bot.subscribeAlways{ this.run(messageQueue::add) }
releaseJob = launch {
while (true) {
delay(CHECK_TIME * 1000)
if (currentTimeSeconds - latestUsed >= CHECK_TIME) {
SessionManager.closeSession(this@AuthedSession)
break
}
}
}
}
override fun close() {
messageQueue.clear()
_listener.complete()
super.close()
}

View File

@ -35,10 +35,7 @@ fun Application.authModule() {
miraiVerify<BindDTO>("/verify", verifiedSessionKey = false) {
val bot = getBotOrThrow(it.qq)
with(SessionManager) {
closeSession(it.sessionKey)
allSession[it.sessionKey] = AuthedSession(bot, EmptyCoroutineContext)
}
SessionManager.createAuthedSession(bot, it.sessionKey)
call.respondStateCode(StateCode.Success)
}