Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't use value class Reset with AtomicRef #863

Merged
merged 5 commits into from
Sep 3, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions rest/src/commonMain/kotlin/ratelimit/AbstractRateLimiter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ import dev.kord.rest.request.Request
import dev.kord.rest.request.RequestIdentifier
import dev.kord.rest.request.identifier
import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.update
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.delay
import kotlinx.coroutines.sync.Mutex
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import mu.KLogger
import kotlin.time.Duration.Companion.minutes

public abstract class AbstractRateLimiter internal constructor(public val clock: Clock) : RequestRateLimiter {
internal abstract val logger: KLogger

private val autoBanRateLimiter = IntervalRateLimiter(limit = 25000, interval = 10.minutes)
private val globalSuspensionPoint = atomic(Reset(clock.now()))
private val globalSuspensionPoint = atomic(clock.now())
internal val buckets = ConcurrentHashMap<BucketKey, Bucket>()
private val routeBuckets = ConcurrentHashMap<RequestIdentifier, MutableSet<BucketKey>>()

internal val BucketKey.bucket get() = buckets.getOrPut(this) { Bucket(this) }
private val Request<*, *>.buckets get() = routeBuckets[identifier].orEmpty().map { it.bucket }
internal fun RequestIdentifier.addBucket(id: BucketKey) = routeBuckets.getOrPut(this) { mutableSetOf() }.add(id)

internal suspend fun Reset.await() {
val duration = value - clock.now()
private suspend fun Instant.await() {
val duration = this - clock.now()
if (duration.isNegative()) return
delay(duration)
}
Expand Down Expand Up @@ -67,7 +67,7 @@ public abstract class AbstractRateLimiter internal constructor(public val clock:
when (response) {
is RequestResponse.GlobalRateLimit -> {
logger.trace { "[RATE LIMIT]:[GLOBAL]:exhausted until ${response.reset.value}" }
globalSuspensionPoint.update { response.reset }
globalSuspensionPoint.value = response.reset.value
}
is RequestResponse.BucketRateLimit -> {
logger.trace { "[RATE LIMIT]:[BUCKET]:Bucket ${response.bucketKey.value} was exhausted until ${response.reset.value}" }
Expand All @@ -83,7 +83,7 @@ public abstract class AbstractRateLimiter internal constructor(public val clock:
}

internal inner class Bucket(val id: BucketKey) {
private val reset = atomic(Reset(clock.now()))
private val reset = atomic(clock.now())
private val mutex = Mutex()

suspend fun awaitAndLock() {
Expand All @@ -93,7 +93,7 @@ public abstract class AbstractRateLimiter internal constructor(public val clock:
}

fun updateReset(newValue: Reset) {
reset.update { newValue }
reset.value = newValue.value
}

fun unlock() = mutex.unlock()
Expand Down