Skip to content

Commit

Permalink
Don't change public API, just use Instant in internals
Browse files Browse the repository at this point in the history
  • Loading branch information
lukellmann committed Sep 3, 2023
1 parent e08adf5 commit 54c42ed
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 29 deletions.
48 changes: 27 additions & 21 deletions rest/api/rest.api
Original file line number Diff line number Diff line change
Expand Up @@ -5934,36 +5934,38 @@ public abstract class dev/kord/rest/ratelimit/RequestResponse {
public static final field Companion Ldev/kord/rest/ratelimit/RequestResponse$Companion;
public abstract fun getBucketKey-JBzVXgM ()Ljava/lang/String;
public abstract fun getRateLimit ()Ldev/kord/rest/ratelimit/RateLimit;
public abstract fun getReset ()Ldev/kord/rest/ratelimit/Reset;
public abstract fun getReset-8536Nbg ()Lkotlinx/datetime/Instant;
}

public final class dev/kord/rest/ratelimit/RequestResponse$Accepted : dev/kord/rest/ratelimit/RequestResponse {
public synthetic fun <init> (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-JBzVXgM ()Ljava/lang/String;
public final fun component2 ()Ldev/kord/rest/ratelimit/RateLimit;
public final fun component3 ()Ldev/kord/rest/ratelimit/Reset;
public final fun copy-Rgdz8z0 (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;)Ldev/kord/rest/ratelimit/RequestResponse$Accepted;
public static synthetic fun copy-Rgdz8z0$default (Ldev/kord/rest/ratelimit/RequestResponse$Accepted;Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;ILjava/lang/Object;)Ldev/kord/rest/ratelimit/RequestResponse$Accepted;
public final fun component3-Ad4v_Ag ()Lkotlinx/datetime/Instant;
public final fun copy-ociLOyk (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;)Ldev/kord/rest/ratelimit/RequestResponse$Accepted;
public static synthetic fun copy-ociLOyk$default (Ldev/kord/rest/ratelimit/RequestResponse$Accepted;Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;ILjava/lang/Object;)Ldev/kord/rest/ratelimit/RequestResponse$Accepted;
public fun equals (Ljava/lang/Object;)Z
public fun getBucketKey-JBzVXgM ()Ljava/lang/String;
public fun getRateLimit ()Ldev/kord/rest/ratelimit/RateLimit;
public fun getReset ()Ldev/kord/rest/ratelimit/Reset;
public synthetic fun getReset-8536Nbg ()Lkotlinx/datetime/Instant;
public fun getReset-Ad4v_Ag ()Lkotlinx/datetime/Instant;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class dev/kord/rest/ratelimit/RequestResponse$BucketRateLimit : dev/kord/rest/ratelimit/RequestResponse {
public synthetic fun <init> (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-M0WuMHw ()Ljava/lang/String;
public final fun component2 ()Ldev/kord/rest/ratelimit/RateLimit;
public final fun component3 ()Ldev/kord/rest/ratelimit/Reset;
public final fun copy-Ec6c71U (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;)Ldev/kord/rest/ratelimit/RequestResponse$BucketRateLimit;
public static synthetic fun copy-Ec6c71U$default (Ldev/kord/rest/ratelimit/RequestResponse$BucketRateLimit;Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;ILjava/lang/Object;)Ldev/kord/rest/ratelimit/RequestResponse$BucketRateLimit;
public final fun component3-Ad4v_Ag ()Lkotlinx/datetime/Instant;
public final fun copy-L_klSFE (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;)Ldev/kord/rest/ratelimit/RequestResponse$BucketRateLimit;
public static synthetic fun copy-L_klSFE$default (Ldev/kord/rest/ratelimit/RequestResponse$BucketRateLimit;Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;ILjava/lang/Object;)Ldev/kord/rest/ratelimit/RequestResponse$BucketRateLimit;
public fun equals (Ljava/lang/Object;)Z
public synthetic fun getBucketKey-JBzVXgM ()Ljava/lang/String;
public fun getBucketKey-M0WuMHw ()Ljava/lang/String;
public fun getRateLimit ()Ldev/kord/rest/ratelimit/RateLimit;
public fun getReset ()Ldev/kord/rest/ratelimit/Reset;
public synthetic fun getReset-8536Nbg ()Lkotlinx/datetime/Instant;
public fun getReset-Ad4v_Ag ()Lkotlinx/datetime/Instant;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
Expand All @@ -5975,20 +5977,21 @@ public final class dev/kord/rest/ratelimit/RequestResponse$Error : dev/kord/rest
public static final field INSTANCE Ldev/kord/rest/ratelimit/RequestResponse$Error;
public fun getBucketKey-JBzVXgM ()Ljava/lang/String;
public fun getRateLimit ()Ldev/kord/rest/ratelimit/RateLimit;
public fun getReset ()Ldev/kord/rest/ratelimit/Reset;
public fun getReset-8536Nbg ()Lkotlinx/datetime/Instant;
}

public final class dev/kord/rest/ratelimit/RequestResponse$GlobalRateLimit : dev/kord/rest/ratelimit/RequestResponse {
public synthetic fun <init> (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-JBzVXgM ()Ljava/lang/String;
public final fun component2 ()Ldev/kord/rest/ratelimit/RateLimit;
public final fun component3 ()Ldev/kord/rest/ratelimit/Reset;
public final fun copy-Rgdz8z0 (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;)Ldev/kord/rest/ratelimit/RequestResponse$GlobalRateLimit;
public static synthetic fun copy-Rgdz8z0$default (Ldev/kord/rest/ratelimit/RequestResponse$GlobalRateLimit;Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Ldev/kord/rest/ratelimit/Reset;ILjava/lang/Object;)Ldev/kord/rest/ratelimit/RequestResponse$GlobalRateLimit;
public final fun component3-Ad4v_Ag ()Lkotlinx/datetime/Instant;
public final fun copy-ociLOyk (Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;)Ldev/kord/rest/ratelimit/RequestResponse$GlobalRateLimit;
public static synthetic fun copy-ociLOyk$default (Ldev/kord/rest/ratelimit/RequestResponse$GlobalRateLimit;Ljava/lang/String;Ldev/kord/rest/ratelimit/RateLimit;Lkotlinx/datetime/Instant;ILjava/lang/Object;)Ldev/kord/rest/ratelimit/RequestResponse$GlobalRateLimit;
public fun equals (Ljava/lang/Object;)Z
public fun getBucketKey-JBzVXgM ()Ljava/lang/String;
public fun getRateLimit ()Ldev/kord/rest/ratelimit/RateLimit;
public fun getReset ()Ldev/kord/rest/ratelimit/Reset;
public synthetic fun getReset-8536Nbg ()Lkotlinx/datetime/Instant;
public fun getReset-Ad4v_Ag ()Lkotlinx/datetime/Instant;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
Expand All @@ -5999,14 +6002,17 @@ public abstract interface class dev/kord/rest/ratelimit/RequestToken {
}

public final class dev/kord/rest/ratelimit/Reset {
public fun <init> (Lkotlinx/datetime/Instant;)V
public final fun component1 ()Lkotlinx/datetime/Instant;
public final fun copy (Lkotlinx/datetime/Instant;)Ldev/kord/rest/ratelimit/Reset;
public static synthetic fun copy$default (Ldev/kord/rest/ratelimit/Reset;Lkotlinx/datetime/Instant;ILjava/lang/Object;)Ldev/kord/rest/ratelimit/Reset;
public static final synthetic fun box-impl (Lkotlinx/datetime/Instant;)Ldev/kord/rest/ratelimit/Reset;
public static fun constructor-impl (Lkotlinx/datetime/Instant;)Lkotlinx/datetime/Instant;
public fun equals (Ljava/lang/Object;)Z
public static fun equals-impl (Lkotlinx/datetime/Instant;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Lkotlinx/datetime/Instant;Lkotlinx/datetime/Instant;)Z
public final fun getValue ()Lkotlinx/datetime/Instant;
public fun hashCode ()I
public static fun hashCode-impl (Lkotlinx/datetime/Instant;)I
public fun toString ()Ljava/lang/String;
public static fun toString-impl (Lkotlinx/datetime/Instant;)Ljava/lang/String;
public final synthetic fun unbox-impl ()Lkotlinx/datetime/Instant;
}

public final class dev/kord/rest/ratelimit/Total {
Expand Down
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
3 changes: 2 additions & 1 deletion rest/src/commonMain/kotlin/ratelimit/RequestRateLimiter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public value class BucketKey(public val value: String)
/**
* The [instant][value] when the current bucket gets reset.
*/
public data class Reset(public val value: Instant)
@JvmInline
public value class Reset(public val value: Instant)

public sealed class RequestResponse {
public abstract val bucketKey: BucketKey?
Expand Down

0 comments on commit 54c42ed

Please sign in to comment.