private async Task RunAsync() { while (_requests.TryDequeue(out var request)) { using (request) { if (LastRateLimit?.Remaining == 0) { var delay = request.RateLimitOverride != null ? TimeSpan.FromMilliseconds(request.RateLimitOverride.Value) : LastRateLimit.ResetsAfter; if (delay > TimeSpan.Zero) { if (request.Options.MaximumRateLimitDuration != default && delay > request.Options.MaximumRateLimitDuration) { request.SetException(new SkyDiscordHttpException((HttpStatusCode)429, null, "Rate-limit hit. Throwing due to Options.ThrowOnRateLimits.")); continue; } await Task.Delay(delay).ConfigureAwait(false); } } try { LastRateLimit = await _rateLimiter.Client.HandleRequestAsync(request).ConfigureAwait(false); } catch (Exception ex) { request.SetException(ex); } } } }
public async Task HandleRateLimitedAsync(RestRequest request, RateLimit rateLimit) { // TODO: proper rate-limit handling! (semaphore for global rates? / throw?) // (also move to SkyDiscord's buckets) var severity = rateLimit.IsGlobal ? LogSeverity.Error : LogSeverity.Warning; var message = $"{(rateLimit.IsGlobal ? "Globally rate" : "Rate")} limited {request} for {rateLimit.ResetsAfter}"; if (request.Options.MaximumRateLimitDuration != default && rateLimit.ResetsAfter > request.Options.MaximumRateLimitDuration) { request.SetException(new SkyDiscordHttpException((HttpStatusCode)429, null, "Rate-limit hit. Throwing due to Options.ThrowOnRateLimits.")); Client.Log(severity, $"{message} - will be throwing due to Options.ThrowOnRateLimits."); return; } Client.Log(severity, $"{message} - will be delaying."); await Task.Delay(rateLimit.ResetsAfter).ConfigureAwait(false); if (!rateLimit.IsGlobal) { request.Initialise(Client.Serializer); await Client.HandleRequestAsync(request).ConfigureAwait(false); } }