@@ -12,15 +12,15 @@ namespace Discord.Net.Queue | |||||
internal struct GatewayBucket | internal struct GatewayBucket | ||||
{ | { | ||||
private static readonly ImmutableDictionary<GatewayBucketType, GatewayBucket> DefsByType; | private static readonly ImmutableDictionary<GatewayBucketType, GatewayBucket> DefsByType; | ||||
private static readonly ImmutableDictionary<string, GatewayBucket> DefsById; | |||||
private static readonly ImmutableDictionary<BucketId, GatewayBucket> DefsById; | |||||
static GatewayBucket() | static GatewayBucket() | ||||
{ | { | ||||
var buckets = new[] | var buckets = new[] | ||||
{ | { | ||||
new GatewayBucket(GatewayBucketType.Unbucketed, "<gateway-unbucketed>", 120, 60), | |||||
new GatewayBucket(GatewayBucketType.Identify, "<gateway-identify>", 1, 5), | |||||
new GatewayBucket(GatewayBucketType.PresenceUpdate, "<gateway-presenceupdate>", 5, 60), | |||||
new GatewayBucket(GatewayBucketType.Unbucketed, BucketId.Create(null, "<gateway-unbucketed>", null), 120, 60), | |||||
new GatewayBucket(GatewayBucketType.Identify, BucketId.Create(null, "<gateway-identify>", null), 1, 5), | |||||
new GatewayBucket(GatewayBucketType.PresenceUpdate, BucketId.Create(null, "<gateway-presenceupdate>", null), 5, 60), | |||||
}; | }; | ||||
var builder = ImmutableDictionary.CreateBuilder<GatewayBucketType, GatewayBucket>(); | var builder = ImmutableDictionary.CreateBuilder<GatewayBucketType, GatewayBucket>(); | ||||
@@ -28,21 +28,21 @@ namespace Discord.Net.Queue | |||||
builder.Add(bucket.Type, bucket); | builder.Add(bucket.Type, bucket); | ||||
DefsByType = builder.ToImmutable(); | DefsByType = builder.ToImmutable(); | ||||
var builder2 = ImmutableDictionary.CreateBuilder<string, GatewayBucket>(); | |||||
var builder2 = ImmutableDictionary.CreateBuilder<BucketId, GatewayBucket>(); | |||||
foreach (var bucket in buckets) | foreach (var bucket in buckets) | ||||
builder2.Add(bucket.Id, bucket); | builder2.Add(bucket.Id, bucket); | ||||
DefsById = builder2.ToImmutable(); | DefsById = builder2.ToImmutable(); | ||||
} | } | ||||
public static GatewayBucket Get(GatewayBucketType type) => DefsByType[type]; | public static GatewayBucket Get(GatewayBucketType type) => DefsByType[type]; | ||||
public static GatewayBucket Get(string id) => DefsById[id]; | |||||
public static GatewayBucket Get(BucketId id) => DefsById[id]; | |||||
public GatewayBucketType Type { get; } | public GatewayBucketType Type { get; } | ||||
public string Id { get; } | |||||
public BucketId Id { get; } | |||||
public int WindowCount { get; set; } | public int WindowCount { get; set; } | ||||
public int WindowSeconds { get; set; } | public int WindowSeconds { get; set; } | ||||
public GatewayBucket(GatewayBucketType type, string id, int count, int seconds) | |||||
public GatewayBucket(GatewayBucketType type, BucketId id, int count, int seconds) | |||||
{ | { | ||||
Type = type; | Type = type; | ||||
Id = id; | Id = id; | ||||
@@ -110,7 +110,7 @@ namespace Discord.Net.Queue | |||||
else | else | ||||
request.Options.CancelToken = _requestCancelToken; | request.Options.CancelToken = _requestCancelToken; | ||||
var bucket = GetOrCreateBucket(request.Options.BucketId, request); | |||||
var bucket = GetOrCreateBucket(request.Options, request); | |||||
await bucket.SendAsync(request).ConfigureAwait(false); | await bucket.SendAsync(request).ConfigureAwait(false); | ||||
createdTokenSource?.Dispose(); | createdTokenSource?.Dispose(); | ||||
} | } | ||||
@@ -163,7 +163,7 @@ namespace Discord.Net.Queue | |||||
var options = RequestOptions.CreateOrClone(request.Options); | var options = RequestOptions.CreateOrClone(request.Options); | ||||
options.BucketId = globalBucketType.Id; | options.BucketId = globalBucketType.Id; | ||||
var globalRequest = new WebSocketRequest(null, null, false, options); | var globalRequest = new WebSocketRequest(null, null, false, options); | ||||
var globalBucket = GetOrCreateBucket(globalBucketType.Id, globalRequest); | |||||
var globalBucket = GetOrCreateBucket(options, globalRequest); | |||||
await globalBucket.TriggerAsync(id, globalRequest); | await globalBucket.TriggerAsync(id, globalRequest); | ||||
} | } | ||||
internal void ReleaseIdentifySemaphore(int id) | internal void ReleaseIdentifySemaphore(int id) | ||||
@@ -179,7 +179,7 @@ namespace Discord.Net.Queue | |||||
#endif | #endif | ||||
} | } | ||||
private RequestBucket GetOrCreateBucket(string id, IRequest request) | |||||
private RequestBucket GetOrCreateBucket(RequestOptions options, IRequest request) | |||||
{ | { | ||||
var bucketId = options.BucketId; | var bucketId = options.BucketId; | ||||
object obj = _buckets.GetOrAdd(bucketId, x => new RequestBucket(this, request, x)); | object obj = _buckets.GetOrAdd(bucketId, x => new RequestBucket(this, request, x)); | ||||
@@ -25,7 +25,7 @@ namespace Discord.Net.Queue | |||||
public int WindowCount { get; private set; } | public int WindowCount { get; private set; } | ||||
public DateTimeOffset LastAttemptAt { get; private set; } | public DateTimeOffset LastAttemptAt { get; private set; } | ||||
public RequestBucket(RequestQueue queue, IRequest request, string id) | |||||
public RequestBucket(RequestQueue queue, IRequest request, BucketId id) | |||||
{ | { | ||||
_queue = queue; | _queue = queue; | ||||
Id = id; | Id = id; | ||||
@@ -285,7 +285,7 @@ namespace Discord.Net.Queue | |||||
} | } | ||||
} | } | ||||
private void UpdateRateLimit(int id, IRequest request, RateLimitInfo info, bool is429) | |||||
private void UpdateRateLimit(int id, IRequest request, RateLimitInfo info, bool is429, bool redirected = false) | |||||
{ | { | ||||
if (WindowCount == 0) | if (WindowCount == 0) | ||||
return; | return; | ||||
@@ -208,7 +208,7 @@ namespace Discord.API | |||||
bytes = Encoding.UTF8.GetBytes(SerializeJson(payload)); | bytes = Encoding.UTF8.GetBytes(SerializeJson(payload)); | ||||
options.IsGatewayBucket = true; | options.IsGatewayBucket = true; | ||||
if (string.IsNullOrEmpty(options.BucketId)) | |||||
if (options.BucketId == null) | |||||
options.BucketId = GatewayBucket.Get(GatewayBucketType.Unbucketed).Id; | options.BucketId = GatewayBucket.Get(GatewayBucketType.Unbucketed).Id; | ||||
await RequestQueue.SendAsync(new WebSocketRequest(WebSocketClient, bytes, true, options)).ConfigureAwait(false); | await RequestQueue.SendAsync(new WebSocketRequest(WebSocketClient, bytes, true, options)).ConfigureAwait(false); | ||||
await _sentGatewayMessageEvent.InvokeAsync(opCode).ConfigureAwait(false); | await _sentGatewayMessageEvent.InvokeAsync(opCode).ConfigureAwait(false); | ||||