private async Task PostProcessResponse(GitHubResponse response) { // Token revocation handling and abuse. var abuse = false; DateTimeOffset?limitUntil = null; if (response?.Status == HttpStatusCode.Unauthorized) { using (var ctx = _shipContextFactory.CreateInstance()) { var changes = await ctx.RevokeAccessTokens(UserId); await _queueClient.NotifyChanges(changes); } DeactivateOnIdle(); } else if (response.Error?.IsAbuse == true) { abuse = true; limitUntil = response.RetryAfter ?? DateTimeOffset.UtcNow.AddSeconds(60); // Default to 60 seconds. } else if (_rateLimit?.IsExceeded == true) { limitUntil = _rateLimit.Reset; } if (limitUntil != null) { // Don't set _lastRequestLimited until an error is logged _dropRequestAbuse = abuse; _dropRequestsUntil = limitUntil; using (var context = _shipContextFactory.CreateInstance()) { var oldRate = _rateLimit; var newRate = new GitHubRateLimit( oldRate.AccessToken, oldRate.Limit, Math.Min(oldRate.Remaining, GitHubRateLimit.RateLimitFloor - 1), limitUntil.Value); UpdateRateLimit(newRate); // Record in DB for sync notification await context.UpdateRateLimit(newRate); } // Force sync notification var changes = new dmt.ChangeSummary(); changes.Users.Add(UserId); await _queueClient.NotifyChanges(changes); } else if (response.RateLimit != null) { _lastRequestLimited = false; // Normal rate limit tracking UpdateRateLimit(response.RateLimit); } }
private void UpdateRateLimit(GitHubRateLimit rateLimit) { lock (this) { if (_rateLimit == null || _rateLimit.Reset < rateLimit.Reset || _rateLimit.Remaining > rateLimit.Remaining) { _rateLimit = rateLimit; } } }