Browse Source

Improved discord HTTP exceptions

tags/1.0-rc
RogueException 8 years ago
parent
commit
7ef48c5ce5
4 changed files with 43 additions and 17 deletions
  1. +26
    -4
      src/Discord.Net.Core/Net/HttpException.cs
  2. +2
    -2
      src/Discord.Net.Rest/Net/Queue/RequestQueue.cs
  3. +10
    -10
      src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs
  4. +5
    -1
      src/Discord.Net.Rest/Net/RateLimitInfo.cs

+ 26
- 4
src/Discord.Net.Core/Net/HttpException.cs View File

@@ -5,14 +5,36 @@ namespace Discord.Net
{ {
public class HttpException : Exception public class HttpException : Exception
{ {
public HttpStatusCode StatusCode { get; }
public HttpStatusCode HttpCode { get; }
public int? DiscordCode { get; }
public string Reason { get; } public string Reason { get; }


public HttpException(HttpStatusCode statusCode, string reason = null)
: base($"The server responded with error {(int)statusCode} ({statusCode}){(reason != null ? $": \"{reason}\"" : "")}")
public HttpException(HttpStatusCode httpCode, int? discordCode = null, string reason = null)
: base(CreateMessage(httpCode, discordCode, reason))
{ {
StatusCode = statusCode;
HttpCode = httpCode;
DiscordCode = discordCode;
Reason = reason; Reason = reason;
} }

private static string CreateMessage(HttpStatusCode httpCode, int? discordCode = null, string reason = null)
{
string msg;
if (discordCode != null)
{
if (reason != null)
msg = $"The server responded with error {(int)discordCode}: {reason}";
else
msg = $"The server responded with error {(int)discordCode}: {httpCode}";
}
else
{
if (reason != null)
msg = $"The server responded with error {(int)httpCode}: {reason}";
else
msg = $"The server responded with error {(int)httpCode}: {httpCode}";
}
return msg;
}
} }
} }

+ 2
- 2
src/Discord.Net.Rest/Net/Queue/RequestQueue.cs View File

@@ -91,9 +91,9 @@ namespace Discord.Net.Queue
await Task.Delay(millis).ConfigureAwait(false); await Task.Delay(millis).ConfigureAwait(false);
} }
} }
internal void PauseGlobal(RateLimitInfo info, TimeSpan lag)
internal void PauseGlobal(RateLimitInfo info)
{ {
_waitUntil = DateTimeOffset.UtcNow.AddMilliseconds(info.RetryAfter.Value + lag.TotalMilliseconds);
_waitUntil = DateTimeOffset.UtcNow.AddMilliseconds(info.RetryAfter.Value + (info.Lag?.TotalMilliseconds ?? 0.0));
} }


private RequestBucket GetOrCreateBucket(string id, RestRequest request) private RequestBucket GetOrCreateBucket(string id, RestRequest request)


+ 10
- 10
src/Discord.Net.Rest/Net/Queue/RequestQueueBucket.cs View File

@@ -54,12 +54,10 @@ namespace Discord.Net.Queue
#if DEBUG_LIMITS #if DEBUG_LIMITS
Debug.WriteLine($"[{id}] Sending..."); Debug.WriteLine($"[{id}] Sending...");
#endif #endif
TimeSpan lag = default(TimeSpan);
RateLimitInfo info = default(RateLimitInfo); RateLimitInfo info = default(RateLimitInfo);
try try
{ {
var response = await request.SendAsync().ConfigureAwait(false); var response = await request.SendAsync().ConfigureAwait(false);
lag = DateTimeOffset.UtcNow - DateTimeOffset.Parse(response.Headers["Date"]);
info = new RateLimitInfo(response.Headers); info = new RateLimitInfo(response.Headers);


if (response.StatusCode < (HttpStatusCode)200 || response.StatusCode >= (HttpStatusCode)300) if (response.StatusCode < (HttpStatusCode)200 || response.StatusCode >= (HttpStatusCode)300)
@@ -72,14 +70,14 @@ namespace Discord.Net.Queue
#if DEBUG_LIMITS #if DEBUG_LIMITS
Debug.WriteLine($"[{id}] (!) 429 [Global]"); Debug.WriteLine($"[{id}] (!) 429 [Global]");
#endif #endif
_queue.PauseGlobal(info, lag);
_queue.PauseGlobal(info);
} }
else else
{ {
#if DEBUG_LIMITS #if DEBUG_LIMITS
Debug.WriteLine($"[{id}] (!) 429"); Debug.WriteLine($"[{id}] (!) 429");
#endif #endif
UpdateRateLimit(id, request, info, lag, true);
UpdateRateLimit(id, request, info, true);
} }
await _queue.RaiseRateLimitTriggered(Id, info).ConfigureAwait(false); await _queue.RaiseRateLimitTriggered(Id, info).ConfigureAwait(false);
continue; //Retry continue; //Retry
@@ -92,6 +90,7 @@ namespace Discord.Net.Queue


continue; //Retry continue; //Retry
default: default:
int? code = null;
string reason = null; string reason = null;
if (response.Stream != null) if (response.Stream != null)
{ {
@@ -101,12 +100,13 @@ namespace Discord.Net.Queue
using (var jsonReader = new JsonTextReader(reader)) using (var jsonReader = new JsonTextReader(reader))
{ {
var json = JToken.Load(jsonReader); var json = JToken.Load(jsonReader);
reason = json.Value<string>("message");
try { code = json.Value<int>("code"); } catch { };
try { reason = json.Value<string>("message"); } catch { };
} }
} }
catch { } catch { }
} }
throw new HttpException(response.StatusCode, reason);
throw new HttpException(response.StatusCode, code, reason);
} }
} }
else else
@@ -142,7 +142,7 @@ namespace Discord.Net.Queue
}*/ }*/
finally finally
{ {
UpdateRateLimit(id, request, info, lag, false);
UpdateRateLimit(id, request, info, false);
#if DEBUG_LIMITS #if DEBUG_LIMITS
Debug.WriteLine($"[{id}] Stop"); Debug.WriteLine($"[{id}] Stop");
#endif #endif
@@ -214,7 +214,7 @@ namespace Discord.Net.Queue
} }
} }


private void UpdateRateLimit(int id, RestRequest request, RateLimitInfo info, TimeSpan lag, bool is429)
private void UpdateRateLimit(int id, RestRequest request, RateLimitInfo info, bool is429)
{ {
if (WindowCount == 0) if (WindowCount == 0)
return; return;
@@ -250,10 +250,10 @@ namespace Discord.Net.Queue
} }
else if (info.Reset.HasValue) else if (info.Reset.HasValue)
{ {
resetTick = info.Reset.Value.AddSeconds(/*1.0 +*/ lag.TotalSeconds);
resetTick = info.Reset.Value.AddSeconds(info.Lag?.TotalSeconds ?? 1.0);
int diff = (int)(resetTick.Value - DateTimeOffset.UtcNow).TotalMilliseconds; int diff = (int)(resetTick.Value - DateTimeOffset.UtcNow).TotalMilliseconds;
#if DEBUG_LIMITS #if DEBUG_LIMITS
Debug.WriteLine($"[{id}] X-RateLimit-Reset: {info.Reset.Value.ToUnixTimeSeconds()} ({diff} ms, {lag.TotalMilliseconds} ms lag)");
Debug.WriteLine($"[{id}] X-RateLimit-Reset: {info.Reset.Value.ToUnixTimeSeconds()} ({diff} ms, {info.Lag?.TotalMilliseconds} ms lag)");
#endif #endif
} }
else if (request.Options.IsClientBucket && request.Options.BucketId != null) else if (request.Options.IsClientBucket && request.Options.BucketId != null)


+ 5
- 1
src/Discord.Net.Rest/Net/RateLimitInfo.cs View File

@@ -10,6 +10,7 @@ namespace Discord.Net
public int? Remaining { get; } public int? Remaining { get; }
public int? RetryAfter { get; } public int? RetryAfter { get; }
public DateTimeOffset? Reset { get; } public DateTimeOffset? Reset { get; }
public TimeSpan? Lag { get; }


internal RateLimitInfo(Dictionary<string, string> headers) internal RateLimitInfo(Dictionary<string, string> headers)
{ {
@@ -17,8 +18,11 @@ namespace Discord.Net
IsGlobal = headers.TryGetValue("X-RateLimit-Global", out temp) ? bool.Parse(temp) : false; IsGlobal = headers.TryGetValue("X-RateLimit-Global", out temp) ? bool.Parse(temp) : false;
Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) ? int.Parse(temp) : (int?)null; Limit = headers.TryGetValue("X-RateLimit-Limit", out temp) ? int.Parse(temp) : (int?)null;
Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) ? int.Parse(temp) : (int?)null; Remaining = headers.TryGetValue("X-RateLimit-Remaining", out temp) ? int.Parse(temp) : (int?)null;
Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) ? DateTimeUtils.FromUnixSeconds(int.Parse(temp)) : (DateTimeOffset?)null;
Reset = headers.TryGetValue("X-RateLimit-Reset", out temp) ?
DateTimeUtils.FromUnixSeconds(int.Parse(temp)) : (DateTimeOffset?)null;
RetryAfter = headers.TryGetValue("Retry-After", out temp) ? int.Parse(temp) : (int?)null; RetryAfter = headers.TryGetValue("Retry-After", out temp) ? int.Parse(temp) : (int?)null;
Lag = headers.TryGetValue("Date", out temp) ?
DateTimeOffset.UtcNow - DateTimeOffset.Parse(temp) : (TimeSpan?)null;
} }
} }
} }

Loading…
Cancel
Save