From ee21ab88ac1f98d66a6daff8554cb2b2d30b892d Mon Sep 17 00:00:00 2001 From: Tyler Voss Date: Sun, 15 Oct 2023 23:01:16 -0500 Subject: [PATCH] Retry 429s within requester --- RiotSharp/Http/RateLimitedRequester.cs | 32 +++++++++++++++---- .../Misc/HttpRequestMessageExtensions.cs | 18 +++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 RiotSharp/Misc/HttpRequestMessageExtensions.cs diff --git a/RiotSharp/Http/RateLimitedRequester.cs b/RiotSharp/Http/RateLimitedRequester.cs index 1016b831..8be1af91 100644 --- a/RiotSharp/Http/RateLimitedRequester.cs +++ b/RiotSharp/Http/RateLimitedRequester.cs @@ -19,19 +19,21 @@ public class RateLimitedRequester : RequesterBase, IRateLimitedRequester public readonly IDictionary RateLimits; private readonly bool _throwOnDelay; + private readonly int _retryCount; private readonly ConcurrentDictionary _rateLimiters = new ConcurrentDictionary(); /// - public RateLimitedRequester(string apiKey, IDictionary rateLimits, bool throwOnDelay = false) : base(apiKey) + public RateLimitedRequester(string apiKey, IDictionary rateLimits, bool throwOnDelay = false, int retryCount = 3) : base(apiKey) { RateLimits = rateLimits; _throwOnDelay = throwOnDelay; + _retryCount = retryCount; } #region Public Methods /// - public Task CreateGetRequestAsync(string relativeUrl, Region region, List queryParameters = null, + public Task CreateGetRequestAsync(string relativeUrl, Region region, List queryParameters = null, bool useHttps = true) { var host = GetPlatformHost(region); @@ -66,7 +68,7 @@ public async Task CreatePutRequestAsync(string relativeUrl, Region region, var response = await SendAsync(request).ConfigureAwait(false); response.Dispose(); return true; - + } catch (RiotSharpException) { @@ -93,12 +95,30 @@ private RateLimiter GetRateLimiter(Region region) /// The region which's requests should be rate limited private async Task GetRateLimitedResponseContentAsync(HttpRequestMessage request, Region region) { - await GetRateLimiter(region).HandleRateLimitAsync().ConfigureAwait(false); + var numRetries = 0; + Exception lastException = null; - using (var response = await SendAsync(request).ConfigureAwait(false)) + while (numRetries < _retryCount) { - return await GetResponseContentAsync(response).ConfigureAwait(false); + await GetRateLimiter(region).HandleRateLimitAsync().ConfigureAwait(false); + try + { + using (var response = await SendAsync(request).ConfigureAwait(false)) + { + return await GetResponseContentAsync(response).ConfigureAwait(false); + } + } + catch (RiotSharpRateLimitException e) + { + lastException = e; + GetRateLimiter(region).SetRetryAfter(e.RetryAfter); + request = request.Clone(); + numRetries++; + continue; + } } + + throw lastException; } } } diff --git a/RiotSharp/Misc/HttpRequestMessageExtensions.cs b/RiotSharp/Misc/HttpRequestMessageExtensions.cs new file mode 100644 index 00000000..523650c9 --- /dev/null +++ b/RiotSharp/Misc/HttpRequestMessageExtensions.cs @@ -0,0 +1,18 @@ +using System.Net.Http; + +namespace RiotSharp.Misc +{ + public static class HttpRequestMessageExtensions + { + + public static HttpRequestMessage Clone(this HttpRequestMessage req) + { + var newReq = new HttpRequestMessage(req.Method, req.RequestUri); + foreach (var header in req.Headers) + { + newReq.Headers.Add(header.Key, header.Value); + } + return newReq; + } + } +} \ No newline at end of file