From c1cace45d2bafea9d5517c4d66c3cab3cdda65ee Mon Sep 17 00:00:00 2001 From: Shindou Mihou Date: Mon, 5 Aug 2024 05:14:11 +0800 Subject: [PATCH 1/2] feat(latte): add `tryRequestQuota` for applications that do not need to wait for the quota --- .../beemo/latte/util/SuspendingRatelimit.kt | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/latte/src/main/java/gg/beemo/latte/util/SuspendingRatelimit.kt b/latte/src/main/java/gg/beemo/latte/util/SuspendingRatelimit.kt index 52fe13b..673a687 100644 --- a/latte/src/main/java/gg/beemo/latte/util/SuspendingRatelimit.kt +++ b/latte/src/main/java/gg/beemo/latte/util/SuspendingRatelimit.kt @@ -6,32 +6,56 @@ import kotlinx.coroutines.sync.withPermit import kotlin.time.Duration class SuspendingRatelimit(private val burst: Int, private val duration: Duration) { - @Volatile private var remainingQuota: Int = burst + @Volatile private var resetTimestamp: Long = 0 private val quotaRequestSem = Semaphore(1) - fun overrideRatelimit(remainingQuota: Int, resetTimestamp: Long) { + fun overrideRatelimit( + remainingQuota: Int, + resetTimestamp: Long, + ) { this.remainingQuota = remainingQuota this.resetTimestamp = resetTimestamp } + private fun calculateWaitTime(): Long { + return (resetTimestamp - System.currentTimeMillis()).coerceAtLeast(0) + } + + private fun tryResetQuota() { + if (System.currentTimeMillis() >= resetTimestamp) { + remainingQuota = burst + resetTimestamp = System.currentTimeMillis() + duration.inWholeMilliseconds + } + } + suspend fun requestQuota() { quotaRequestSem.withPermit { if (remainingQuota <= 0) { - val waitTime = (resetTimestamp - System.currentTimeMillis()).coerceAtLeast(0) + val waitTime = calculateWaitTime() delay(waitTime) } - if (System.currentTimeMillis() >= resetTimestamp) { - remainingQuota = burst - resetTimestamp = System.currentTimeMillis() + duration.inWholeMilliseconds - } + tryResetQuota() + check(remainingQuota > 0) remainingQuota-- } } + suspend fun tryRequestQuota(): Pair = + quotaRequestSem.withPermit { + if (remainingQuota <= 0) { + val waitTime = calculateWaitTime() + return@withPermit false to waitTime + } + tryResetQuota() + + check(remainingQuota > 0) + remainingQuota-- + return@withPermit true to null + } } From 323514519ab623b1cb875d9734088066287440f8 Mon Sep 17 00:00:00 2001 From: Shindou Mihou Date: Mon, 5 Aug 2024 09:56:57 +0800 Subject: [PATCH 2/2] feat(latte): remove semaphore wrapper --- .../beemo/latte/util/SuspendingRatelimit.kt | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/latte/src/main/java/gg/beemo/latte/util/SuspendingRatelimit.kt b/latte/src/main/java/gg/beemo/latte/util/SuspendingRatelimit.kt index 673a687..c521fe4 100644 --- a/latte/src/main/java/gg/beemo/latte/util/SuspendingRatelimit.kt +++ b/latte/src/main/java/gg/beemo/latte/util/SuspendingRatelimit.kt @@ -46,16 +46,15 @@ class SuspendingRatelimit(private val burst: Int, private val duration: Duration } } - suspend fun tryRequestQuota(): Pair = - quotaRequestSem.withPermit { - if (remainingQuota <= 0) { - val waitTime = calculateWaitTime() - return@withPermit false to waitTime - } - tryResetQuota() - - check(remainingQuota > 0) - remainingQuota-- - return@withPermit true to null + fun tryRequestQuota(): Pair { + if (remainingQuota <= 0) { + val waitTime = calculateWaitTime() + return false to waitTime } + tryResetQuota() + + check(remainingQuota > 0) + remainingQuota-- + return true to null + } }