protected override async Task <HttpResponseMessage> ImplementationAsync(
            Func <Context, CancellationToken, Task <HttpResponseMessage> > action, Context context, CancellationToken ct,
            bool continueOnCapturedContext)
        {
            if (!context.TryGetValue(EndpointContextKey, out var endpointObj) || !(endpointObj is string endpoint))
            {
                throw new ArgumentException("Must provide endpoint in Polly context");
            }

            if (!context.TryGetValue(MajorContextKey, out var majorObj) || !(majorObj is ulong major))
            {
                throw new ArgumentException("Must provide major in Polly context");
            }

            // Check rate limit, throw if we're not allowed...
            _ratelimiter.AllowRequestOrThrow(endpoint, major, DateTimeOffset.Now);

            // We're OK, push it through
            var response = await action(context, ct).ConfigureAwait(continueOnCapturedContext);

            // Update rate limit state with headers
            var headers = RatelimitHeaders.Parse(response);

            _ratelimiter.HandleResponse(headers, endpoint, major);

            return(response);
        }
Example #2
0
    public void HandleResponse(RatelimitHeaders headers, string endpoint, ulong major)
    {
        if (!headers.HasRatelimitInfo)
        {
            return;
        }

        // TODO: properly calculate server time?
        if (headers.Global)
        {
            _logger.Warning(
                "Global rate limit hit, resetting at {GlobalRateLimitExpiry} (in {GlobalRateLimitResetAfter}!",
                _globalRateLimitExpiry, headers.ResetAfter);
            _globalRateLimitExpiry = headers.Reset;
        }
        else
        {
            // Update buckets first, then get it again, to properly "transfer" this info over to the new value
            _buckets.UpdateEndpointInfo(endpoint, headers.Bucket !, headers.Limit);

            var bucket = _buckets.GetBucket(endpoint, major);
            bucket?.HandleResponse(headers);
        }
    }