fix: Ensure resetAt is in the future

If the current reset time is in the past, then somebody else in the
current bucket must have made a request before we were able to. To
prevent accidental ratelimits, we fall-back to the second sleep
branch, as if the reset time wasn't specified at all.

Additionally Extracts the minimum sleep time to a constant, and also
bumps it to 750ms.
This commit is contained in:
FiniteReality
2020-05-18 18:01:23 +01:00
parent d294678ed5
commit 08d9834e2c

View File

@@ -13,6 +13,8 @@ namespace Discord.Net.Queue
{ {
internal class RequestBucket internal class RequestBucket
{ {
private const int MinimumSleepTimeMs = 750;
private readonly object _lock; private readonly object _lock;
private readonly RequestQueue _queue; private readonly RequestQueue _queue;
private int _semaphore; private int _semaphore;
@@ -183,10 +185,11 @@ namespace Discord.Net.Queue
ThrowRetryLimit(request); ThrowRetryLimit(request);
if (resetAt.HasValue) if (resetAt.HasValue && resetAt > DateTimeOffset.UtcNow)
{ {
if (resetAt > timeoutAt) if (resetAt > timeoutAt)
ThrowRetryLimit(request); ThrowRetryLimit(request);
int millis = (int)Math.Ceiling((resetAt.Value - DateTimeOffset.UtcNow).TotalMilliseconds); int millis = (int)Math.Ceiling((resetAt.Value - DateTimeOffset.UtcNow).TotalMilliseconds);
#if DEBUG_LIMITS #if DEBUG_LIMITS
Debug.WriteLine($"[{id}] Sleeping {millis} ms (Pre-emptive)"); Debug.WriteLine($"[{id}] Sleeping {millis} ms (Pre-emptive)");
@@ -196,12 +199,12 @@ namespace Discord.Net.Queue
} }
else else
{ {
if ((timeoutAt.Value - DateTimeOffset.UtcNow).TotalMilliseconds < 500.0) if ((timeoutAt.Value - DateTimeOffset.UtcNow).TotalMilliseconds < MinimumSleepTimeMs)
ThrowRetryLimit(request); ThrowRetryLimit(request);
#if DEBUG_LIMITS #if DEBUG_LIMITS
Debug.WriteLine($"[{id}] Sleeping 500* ms (Pre-emptive)"); Debug.WriteLine($"[{id}] Sleeping {MinimumSleepTimeMs}* ms (Pre-emptive)");
#endif #endif
await Task.Delay(500, request.Options.CancelToken).ConfigureAwait(false); await Task.Delay(MinimumSleepTimeMs, request.Options.CancelToken).ConfigureAwait(false);
} }
continue; continue;
} }