Improved 429 handling
This commit is contained in:
@@ -47,7 +47,7 @@ namespace Discord.Net.Queue
|
||||
RequestQueueBucket bucket;
|
||||
bool success = FindBucket(ex.BucketId, out bucket);
|
||||
|
||||
await _queue.RaiseRateLimitTriggered(ex.BucketId, success ? bucket.Definition : (Bucket)null, ex.RetryAfterMilliseconds).ConfigureAwait(false);
|
||||
await _queue.RaiseRateLimitTriggered(ex.BucketId, success ? bucket.Definition : null, ex.RetryAfterMilliseconds).ConfigureAwait(false);
|
||||
|
||||
bucket.Pause(ex.RetryAfterMilliseconds);
|
||||
}
|
||||
@@ -67,6 +67,7 @@ namespace Discord.Net.Queue
|
||||
//Get our 429 state
|
||||
Task notifier;
|
||||
int resumeTime;
|
||||
|
||||
lock (_pauseLock)
|
||||
{
|
||||
notifier = _resumeNotifier.Task;
|
||||
@@ -133,14 +134,14 @@ namespace Discord.Net.Queue
|
||||
{
|
||||
_resumeNotifier = new TaskCompletionSource<byte>();
|
||||
_pauseEndTick = unchecked(Environment.TickCount + milliseconds);
|
||||
QueueResumeAsync(milliseconds);
|
||||
QueueResumeAsync(_resumeNotifier, milliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
private async Task QueueResumeAsync(int millis)
|
||||
private async Task QueueResumeAsync(TaskCompletionSource<byte> resumeNotifier, int millis)
|
||||
{
|
||||
await Task.Delay(millis).ConfigureAwait(false);
|
||||
_resumeNotifier.SetResult(0);
|
||||
resumeNotifier.SetResult(0);
|
||||
}
|
||||
|
||||
private async Task EnterAsync(int? endTick)
|
||||
@@ -151,8 +152,7 @@ namespace Discord.Net.Queue
|
||||
if (millis <= 0 || !await _semaphore.WaitAsync(millis).ConfigureAwait(false))
|
||||
throw new TimeoutException();
|
||||
}
|
||||
else
|
||||
await _semaphore.WaitAsync().ConfigureAwait(false);
|
||||
await _semaphore.WaitAsync().ConfigureAwait(false);
|
||||
}
|
||||
private async Task QueueExitAsync()
|
||||
{
|
||||
|
||||
@@ -7,9 +7,10 @@ namespace Discord.Net
|
||||
public string BucketId { get; }
|
||||
public int RetryAfterMilliseconds { get; }
|
||||
|
||||
public HttpRateLimitException(int retryAfterMilliseconds)
|
||||
: base((HttpStatusCode)429)
|
||||
public HttpRateLimitException(string bucketId, int retryAfterMilliseconds, string reason)
|
||||
: base((HttpStatusCode)429, reason)
|
||||
{
|
||||
BucketId = bucketId;
|
||||
RetryAfterMilliseconds = retryAfterMilliseconds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,25 +124,32 @@ namespace Discord.Net.Rest
|
||||
int statusCode = (int)response.StatusCode;
|
||||
if (statusCode < 200 || statusCode >= 300) //2xx = Success
|
||||
{
|
||||
if (statusCode == 429)
|
||||
string reason = null;
|
||||
JToken content = null;
|
||||
if (response.Content.Headers.GetValues("content-type").FirstOrDefault() == "application/json")
|
||||
{
|
||||
//TODO: Include bucket info
|
||||
int retryAfterMillis = int.Parse(response.Headers.GetValues("retry-after").First());
|
||||
throw new HttpRateLimitException(retryAfterMillis);
|
||||
try
|
||||
{
|
||||
using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
using (var reader = new StreamReader(stream))
|
||||
using (var json = new JsonTextReader(reader))
|
||||
{
|
||||
content = _errorDeserializer.Deserialize<JToken>(json);
|
||||
reason = content.Value<string>("message");
|
||||
}
|
||||
}
|
||||
catch { } //Might have been HTML Should we check for content-type?
|
||||
}
|
||||
|
||||
string reason = null;
|
||||
try
|
||||
if (statusCode == 429 && content != null)
|
||||
{
|
||||
using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
using (var reader = new StreamReader(stream))
|
||||
using (var json = new JsonTextReader(reader))
|
||||
{
|
||||
reason = (_errorDeserializer.Deserialize(json) as JToken).Value<string>("message");
|
||||
}
|
||||
//TODO: Include bucket info
|
||||
string bucketId = content.Value<string>("bucket");
|
||||
int retryAfterMillis = content.Value<int>("retry_after");
|
||||
throw new HttpRateLimitException(bucketId, retryAfterMillis, reason);
|
||||
}
|
||||
catch { } //Might have been HTML
|
||||
throw new HttpException(response.StatusCode, reason);
|
||||
else
|
||||
throw new HttpException(response.StatusCode, reason);
|
||||
}
|
||||
|
||||
if (headerOnly)
|
||||
|
||||
Reference in New Issue
Block a user