From b2598d37b6debbba972aaeb240980ce691f0671e Mon Sep 17 00:00:00 2001 From: Quin Lynch <49576606+quinchs@users.noreply.github.com> Date: Wed, 16 Feb 2022 08:20:57 -0400 Subject: [PATCH] fix: Implement correct ratelimit handles for 429's (#2110) * init * fix errors --- .../Net/Queue/RequestQueueBucket.cs | 16 +++++++++++++--- src/Discord.Net.Rest/Net/RateLimitInfo.cs | 18 +++++++----------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs index 8130e6fac..3bdfb2ffe 100644 --- a/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs +++ b/src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs @@ -88,7 +88,7 @@ namespace Discord.Net.Queue #if DEBUG_LIMITS Debug.WriteLine($"[{id}] (!) 429"); #endif - UpdateRateLimit(id, request, info, true); + UpdateRateLimit(id, request, info, true, body:response.Stream); } await _queue.RaiseRateLimitTriggered(Id, info, $"{request.Method} {request.Endpoint}").ConfigureAwait(false); continue; //Retry @@ -316,7 +316,7 @@ namespace Discord.Net.Queue } } - private void UpdateRateLimit(int id, IRequest request, RateLimitInfo info, bool is429, bool redirected = false) + private void UpdateRateLimit(int id, IRequest request, RateLimitInfo info, bool is429, bool redirected = false, Stream body = null) { if (WindowCount == 0) return; @@ -373,7 +373,17 @@ namespace Discord.Net.Queue Debug.WriteLine($"[{id}] X-RateLimit-Remaining: " + info.Remaining.Value); _semaphore = info.Remaining.Value; }*/ - if (info.RetryAfter.HasValue) + if (is429) + { + // use the payload reset after value + var payload = info.ReadRatelimitPayload(body); + + resetTick = DateTimeOffset.UtcNow.Add(TimeSpan.FromSeconds(payload.RetryAfter)); +#if DEBUG_LIMITS + Debug.WriteLine($"[{id}] Reset-After: {info.ResetAfter.Value} ({info.ResetAfter?.TotalMilliseconds} ms)"); +#endif + } + else if (info.RetryAfter.HasValue) { //RetryAfter is more accurate than Reset, where available resetTick = DateTimeOffset.UtcNow.AddSeconds(info.RetryAfter.Value); diff --git a/src/Discord.Net.Rest/Net/RateLimitInfo.cs b/src/Discord.Net.Rest/Net/RateLimitInfo.cs index 253343311..9d0b9a426 100644 --- a/src/Discord.Net.Rest/Net/RateLimitInfo.cs +++ b/src/Discord.Net.Rest/Net/RateLimitInfo.cs @@ -61,22 +61,18 @@ namespace Discord.Net DateTimeOffset.TryParse(temp, CultureInfo.InvariantCulture, DateTimeStyles.None, out var date) ? DateTimeOffset.UtcNow - date : (TimeSpan?)null; } - internal void ReadRatelimitPayload(Stream response) + internal Ratelimit ReadRatelimitPayload(Stream response) { - try + if (response != null && response.Length != 0) { - if (response != null && response.Length != 0) + using (TextReader text = new StreamReader(response)) + using (JsonReader reader = new JsonTextReader(text)) { - using (TextReader text = new StreamReader(response)) - using (JsonReader reader = new JsonTextReader(text)) - { - var ratelimit = Discord.Rest.DiscordRestClient.Serializer.Deserialize(reader); - - ResetAfter = TimeSpan.FromSeconds(ratelimit.RetryAfter); - } + return Discord.Rest.DiscordRestClient.Serializer.Deserialize(reader); } } - catch { } + + return null; } } }