mirror of
https://github.com/InsanusMokrassar/SauceNaoAPI.git
synced 2024-06-03 00:15:13 +00:00
75 lines
2.4 KiB
Kotlin
75 lines
2.4 KiB
Kotlin
|
package com.github.insanusmokrassar.SauceNaoAPI.utils
|
||
|
|
||
|
import com.github.insanusmokrassar.SauceNaoAPI.additional.LONG_TIME_RECALCULATING_MILLIS
|
||
|
import com.github.insanusmokrassar.SauceNaoAPI.additional.SHORT_TIME_RECALCULATING_MILLIS
|
||
|
import com.github.insanusmokrassar.SauceNaoAPI.models.Header
|
||
|
import kotlinx.coroutines.*
|
||
|
import kotlinx.coroutines.channels.Channel
|
||
|
import kotlinx.io.core.Closeable
|
||
|
import org.joda.time.DateTime
|
||
|
import kotlin.coroutines.suspendCoroutine
|
||
|
import kotlin.math.min
|
||
|
|
||
|
class RequestQuotaManager (
|
||
|
private val scope: CoroutineScope
|
||
|
) : Closeable {
|
||
|
private var longQuota = 1
|
||
|
private var shortQuota = 1
|
||
|
private var longMaxQuota = 1
|
||
|
private var shortMaxQuota = 1
|
||
|
|
||
|
private val quotaActions = Channel<suspend () -> Unit>(Channel.UNLIMITED)
|
||
|
|
||
|
private val quotaJob = scope.launch {
|
||
|
for (callback in quotaActions) {
|
||
|
callback()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
suspend fun updateQuota(header: Header, timeManager: TimeManager) {
|
||
|
quotaActions.send(
|
||
|
suspend {
|
||
|
longMaxQuota = header.longLimit
|
||
|
shortMaxQuota = header.shortLimit
|
||
|
|
||
|
longQuota = min(header.longLimit, header.longRemaining)
|
||
|
shortQuota = min(header.shortLimit, header.shortRemaining)
|
||
|
|
||
|
when {
|
||
|
shortQuota < 1 -> timeManager.getMostOldestInShortPeriod() ?.millis ?.plus(SHORT_TIME_RECALCULATING_MILLIS) ?: let {
|
||
|
shortQuota = 1
|
||
|
null
|
||
|
}
|
||
|
longQuota < 1 -> timeManager.getMostOldestInLongPeriod() ?.millis ?.plus(LONG_TIME_RECALCULATING_MILLIS) ?: let {
|
||
|
longQuota = 1
|
||
|
null
|
||
|
}
|
||
|
else -> null
|
||
|
} ?.let {
|
||
|
delay(it - DateTime.now().millis)
|
||
|
}
|
||
|
Unit
|
||
|
}
|
||
|
)
|
||
|
}
|
||
|
|
||
|
suspend fun getQuota() {
|
||
|
return suspendCoroutine {
|
||
|
lateinit var callback: suspend () -> Unit
|
||
|
callback = suspend {
|
||
|
if (longQuota > 0 && shortQuota > 0) {
|
||
|
it.resumeWith(Result.success(Unit))
|
||
|
} else {
|
||
|
quotaActions.send(callback)
|
||
|
}
|
||
|
}
|
||
|
quotaActions.offer(callback)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
override fun close() {
|
||
|
quotaJob.cancel()
|
||
|
quotaActions.close()
|
||
|
}
|
||
|
}
|