コード例 #1
0
            private async Task RunAsync()
            {
                var reader = _requests.Reader;

                await foreach (var request in reader.ReadAllAsync())
                {
                    bool retry;
                    do
                    {
                        retry = false;
                        try
                        {
                            if (_isUnlimited)
                            {
                                var bucket = _rateLimiter.GetBucket(request.Route, false);
                                if (bucket != this)
                                {
                                    Logger.LogDebug("Route {0} is moving the request to the limited bucket.", request.Route);
                                    bucket.Post(request);
                                    break;
                                }
                            }

                            var now                   = DateTimeOffset.UtcNow;
                            var globalResetsAt        = _rateLimiter._globalResetsAt;
                            var isGloballyRateLimited = globalResetsAt > now;
                            if (Remaining == 0 || isGloballyRateLimited)
                            {
                                var delay = isGloballyRateLimited
                                    ? globalResetsAt.Value - now
                                    : ResetsAt - now;

                                if (delay > TimeSpan.Zero)
                                {
                                    var maximumDelayDuration = (request.Options as DefaultRestRequestOptions)?.MaximumDelayDuration ?? _rateLimiter.MaximumDelayDuration;
                                    if (maximumDelayDuration != Timeout.InfiniteTimeSpan && delay > maximumDelayDuration)
                                    {
                                        Logger.LogDebug("Route {0} is rate-limited - throwing as the delay {1} exceeds the maximum delay duration.", request.Route, delay);
                                        request.Complete(new MaximumRateLimitDelayExceededException(delay, isGloballyRateLimited));
                                        break;
                                    }

                                    var level = request.Route.BaseRoute.Equals(Route.Channel.CreateReaction)
                                        ? LogLevel.Debug
                                        : LogLevel.Information;

                                    Logger.Log(level, "Route {0} is rate-limited - delaying for {1}.", request.Route, delay);
                                    await Task.Delay(delay).ConfigureAwait(false);
                                }
                            }

                            var response = await _rateLimiter.ApiClient.Requester.ExecuteAsync(request).ConfigureAwait(false);

                            if (_rateLimiter.UpdateBucket(request.Route, response.HttpResponse))
                            {
                                Logger.LogInformation("Route {0} is retrying the last request due to a hit rate-limit.", request.Route);
                                retry = true;
                            }
                            else
                            {
                                request.Complete(response);
                                request.Dispose();
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.LogError(ex, "Route {0} encountered an exception while processing a request.", request.Route);
                            request.Dispose();
                        }
                    }while (retry);
                }
            }
コード例 #2
0
            private async Task RunAsync()
            {
                //Logger.LogTrace("Bucket {0} is running {1} requests.", Id, _requests.Count);
                LinkedListNode <IRestRequest> requestNode;

                while ((requestNode = _requests.First) != null)
                {
                    var request = requestNode.Value;
                    _requests.RemoveFirst();
                    if (Remaining == 0)
                    {
                        var delay = ResetsAt - DateTimeOffset.UtcNow;
                        if (delay > TimeSpan.Zero)
                        {
                            if (_rateLimiter.MaximumDelayDuration != Timeout.InfiniteTimeSpan && delay > _rateLimiter.MaximumDelayDuration)
                            {
                                Logger.LogWarning("Bucket {0} is pre-emptively rate-limiting, throwing as the delay {1} exceeds the maximum delay duration.", Id, delay);
                                // TODO: MaximumDelayDurationExceededException
                                request.Complete(new TimeoutException());
                                continue;
                            }

                            var level = request.Route.BaseRoute == Route.Channel.CreateReaction
                                ? LogLevel.Debug
                                : LogLevel.Information;
                            Logger.Log(level, "Bucket {0} is pre-emptively rate-limiting, delaying for {1}.", Id, delay);
                            await Task.Delay(delay).ConfigureAwait(false);
                        }
                    }

                    // If this bucket is unlimited we check if there's a proper bucket created and move the requests accordingly.
                    if (IsUnlimited)
                    {
                        var bucket = _rateLimiter.GetBucket(request.Route, false);
                        if (bucket != this)
                        {
                            Logger.LogDebug("Bucket {0} is moving the request to the limited bucket {1}.", Id, bucket);
                            bucket.Enqueue(request);
                            continue;
                        }
                    }

                    try
                    {
                        var response = await _rateLimiter.ApiClient.Requester.ExecuteAsync(request).ConfigureAwait(false);

                        if (_rateLimiter.UpdateBucket(request.Route, response.HttpResponse))
                        {
                            Logger.LogInformation("Bucket {0} is re-enqueuing the last request due to a hit rate-limit.", Id);
                            _requests.AddFirst(request);
                        }
                        else
                        {
                            request.Complete(response);
                            request.Dispose();
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError(ex, "Bucket {0} encountered an exception when executing a request.", Id);
                    }
                }
            }