mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-11-22 08:13:47 +00:00
add CommonLimiter
This commit is contained in:
parent
ac5d3214b4
commit
1bdcf3ae60
@ -52,6 +52,7 @@ media for present out)
|
|||||||
### 0.12.4 UpdatesPoller optimisations
|
### 0.12.4 UpdatesPoller optimisations
|
||||||
|
|
||||||
* Optimized preparing of media group in `UpdatesPoller`
|
* Optimized preparing of media group in `UpdatesPoller`
|
||||||
|
* Add `CommonLimiter`
|
||||||
|
|
||||||
## 0.11.0
|
## 0.11.0
|
||||||
|
|
||||||
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters
|
||||||
|
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
|
||||||
|
private fun now(): Long = System.currentTimeMillis()
|
||||||
|
|
||||||
|
class CommonLimiter(
|
||||||
|
private val lockCount: Int = 10,
|
||||||
|
private val regenTime: Long = 20 * 1000L // 20 seconds for full regen of opportunity to send message
|
||||||
|
) : RequestLimiter {
|
||||||
|
private var doLimit: Boolean = false
|
||||||
|
|
||||||
|
private val counterChannel = Channel<Unit>(Channel.UNLIMITED)
|
||||||
|
private val scope = CoroutineScope(Dispatchers.Default)
|
||||||
|
private val counterJob = scope.launch {
|
||||||
|
var wasLastSecond = 0
|
||||||
|
var lastCountTime = now()
|
||||||
|
var limitManagementJob: Job? = null
|
||||||
|
var removeLimitTime: Long = lastCountTime
|
||||||
|
for (counter in counterChannel) {
|
||||||
|
val now = now()
|
||||||
|
if (now - lastCountTime > 1000) {
|
||||||
|
lastCountTime = now
|
||||||
|
wasLastSecond = 1
|
||||||
|
} else {
|
||||||
|
wasLastSecond++
|
||||||
|
}
|
||||||
|
if (wasLastSecond >= lockCount) {
|
||||||
|
removeLimitTime = now + regenTime
|
||||||
|
if (limitManagementJob == null) {
|
||||||
|
limitManagementJob = launch {
|
||||||
|
doLimit = true
|
||||||
|
var internalNow = now()
|
||||||
|
while (internalNow < removeLimitTime) {
|
||||||
|
delay(removeLimitTime - internalNow)
|
||||||
|
internalNow = now()
|
||||||
|
}
|
||||||
|
doLimit = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (now > removeLimitTime) {
|
||||||
|
limitManagementJob = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val quoterChannel = Channel<Unit>(Channel.CONFLATED)
|
||||||
|
private val tickerJob = scope.launch {
|
||||||
|
while (isActive) {
|
||||||
|
quoterChannel.send(Unit)
|
||||||
|
delay(1000L)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun <T> limit(block: suspend () -> T): T {
|
||||||
|
counterChannel.send(Unit)
|
||||||
|
return if (!doLimit) {
|
||||||
|
block()
|
||||||
|
} else {
|
||||||
|
quoterChannel.receive()
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user