mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-11-22 08:13:47 +00:00
RequestLimiter
This commit is contained in:
parent
d7a77085b5
commit
e77478b13e
@ -49,3 +49,4 @@
|
|||||||
`com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor` package
|
`com.github.insanusmokrassar.TelegramBotAPI.bot.Ktor` package
|
||||||
* Replace `ProxySettings` data class in `settings` package, deprecate old link
|
* Replace `ProxySettings` data class in `settings` package, deprecate old link
|
||||||
* `BaseRequestsExecutor` now have no it's own scope
|
* `BaseRequestsExecutor` now have no it's own scope
|
||||||
|
* Add `RequestLimiter` and base realisations
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters
|
||||||
|
|
||||||
|
object EmptyLimiter : RequestLimiter {
|
||||||
|
override suspend fun <T> limit(block: suspend () -> T): T = block()
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters
|
||||||
|
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.serialization.Optional
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import kotlin.coroutines.*
|
||||||
|
|
||||||
|
private sealed class RequestEvent
|
||||||
|
private class AddRequest(
|
||||||
|
val continuation: Continuation<Long>
|
||||||
|
) : RequestEvent()
|
||||||
|
private object CompleteRequest : RequestEvent()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class PowLimiter(
|
||||||
|
@Optional
|
||||||
|
private val minAwaitTime: Long = 0L,
|
||||||
|
@Optional
|
||||||
|
private val maxAwaitTime: Long = 10000L,
|
||||||
|
@Optional
|
||||||
|
private val powValue: Double = 4.0,
|
||||||
|
@Optional
|
||||||
|
private val powK: Double = 0.0016
|
||||||
|
) : RequestLimiter {
|
||||||
|
private val scope = CoroutineScope(
|
||||||
|
Executors.newFixedThreadPool(3).asCoroutineDispatcher()
|
||||||
|
)
|
||||||
|
private val eventsChannel = Channel<RequestEvent>(Channel.UNLIMITED)
|
||||||
|
private val awaitTimeRange = minAwaitTime .. maxAwaitTime
|
||||||
|
|
||||||
|
init {
|
||||||
|
scope.launch {
|
||||||
|
var requestsInWork: Double = 0.0
|
||||||
|
for (event in eventsChannel) {
|
||||||
|
when (event) {
|
||||||
|
is AddRequest -> {
|
||||||
|
val awaitTime = ((Math.pow(requestsInWork, powValue) * powK) * 1000L).toLong()
|
||||||
|
requestsInWork++
|
||||||
|
|
||||||
|
event.continuation.resume(
|
||||||
|
if (awaitTime in awaitTimeRange) {
|
||||||
|
awaitTime
|
||||||
|
} else {
|
||||||
|
if (awaitTime < minAwaitTime) {
|
||||||
|
minAwaitTime
|
||||||
|
} else {
|
||||||
|
maxAwaitTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is CompleteRequest -> requestsInWork--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun <T> limit(
|
||||||
|
block: suspend () -> T
|
||||||
|
): T {
|
||||||
|
val delayMillis = suspendCoroutine<Long> {
|
||||||
|
scope.launch { eventsChannel.send(AddRequest(it)) }
|
||||||
|
}
|
||||||
|
delay(delayMillis)
|
||||||
|
return try {
|
||||||
|
block()
|
||||||
|
} finally {
|
||||||
|
eventsChannel.send(CompleteRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters
|
||||||
|
|
||||||
|
interface RequestLimiter {
|
||||||
|
/**
|
||||||
|
* Use limit for working of block (like delay between or after, for example)
|
||||||
|
*/
|
||||||
|
suspend fun <T> limit(block: suspend () -> T): T
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user