diff --git a/src/Discord.Net.Rest/Entities/Gateway/GatewayLimit.cs b/src/Discord.Net.Rest/Entities/Gateway/GatewayLimit.cs deleted file mode 100644 index 3b229dbb9..000000000 --- a/src/Discord.Net.Rest/Entities/Gateway/GatewayLimit.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace Discord.Rest -{ - /// - /// Represents the limits for a gateway request. - /// - public struct GatewayLimit - { - /// - /// Gets or sets the maximum amount of this type of request in a time frame, that is set by . - /// - /// - /// Returns the maximum amount of this type of request in a time frame to not trigger the rate limit. - /// - public int Count { get; set; } - /// - /// Gets or sets the amount of seconds until the rate limiter resets the remaining requests back to . - /// - /// - /// Returns the amount of seconds that define the time frame to reset. - /// - public int Seconds { get; set; } - - internal GatewayLimit(int count, int seconds) - { - Count = count; - Seconds = seconds; - } - } -} diff --git a/src/Discord.Net.Rest/Entities/Gateway/GatewayLimits.cs b/src/Discord.Net.Rest/Entities/Gateway/GatewayLimits.cs deleted file mode 100644 index 78cef9b69..000000000 --- a/src/Discord.Net.Rest/Entities/Gateway/GatewayLimits.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; - -namespace Discord.Rest -{ - /// - /// Contains the rate limits for the gateway. - /// - public class GatewayLimits - { - /// - /// Creates a new with the default values. - /// - public static GatewayLimits Default => new GatewayLimits(); - - /// - /// Gets or sets the global limits for the gateway rate limiter. - /// - /// - /// This property includes all the other limits, like Identify, - /// and it is per websocket. - /// - public GatewayLimit Global { get; set; } - - /// - /// Gets or sets the limits of Identify requests. - /// - /// - /// This limit is included into but it is - /// also per account. - /// - public GatewayLimit Identify { get; set; } - - /// - /// Gets or sets the limits of Presence Update requests. - /// - /// - /// Presence updates include activity (playing, watching, etc) - /// and status (online, idle, etc) - /// - public GatewayLimit PresenceUpdate { get; set; } - - /// - /// Gets or sets the name of the master - /// used by identify. - /// - /// - /// It is used to define what slave - /// is free to run for concurrent identify requests. - /// - public string IdentifyMasterSemaphoreName { get; set; } - - /// - /// Gets or sets the name of the slave - /// used by identify. - /// - /// - /// If the maximum concurrency is higher than one and you are using the sharded client, - /// it will be dinamilly renamed to fit the necessary needs. - /// - public string IdentifySemaphoreName { get; set; } - - /// - /// Gets or sets the maximum identify concurrency. - /// - /// - /// This limit is provided by Discord. - /// - public int IdentifyMaxConcurrency { get; set; } - - /// - /// Initializes a new with the default values. - /// - public GatewayLimits() - { - Global = new GatewayLimit(120, 60); - Identify = new GatewayLimit(1, 5); - PresenceUpdate = new GatewayLimit(5, 60); - IdentifyMasterSemaphoreName = Guid.NewGuid().ToString(); - IdentifySemaphoreName = Guid.NewGuid().ToString(); - IdentifyMaxConcurrency = 1; - } - - internal GatewayLimits(GatewayLimits limits) - { - Global = new GatewayLimit(limits.Global.Count, limits.Global.Seconds); - Identify = new GatewayLimit(limits.Identify.Count, limits.Identify.Seconds); - PresenceUpdate = new GatewayLimit(limits.PresenceUpdate.Count, limits.PresenceUpdate.Seconds); - IdentifyMasterSemaphoreName = limits.IdentifyMasterSemaphoreName; - IdentifySemaphoreName = limits.IdentifySemaphoreName; - IdentifyMaxConcurrency = limits.IdentifyMaxConcurrency; - } - - - internal static GatewayLimits GetOrCreate(GatewayLimits limits) - => limits ?? Default; - - public GatewayLimits Clone() - => new GatewayLimits(this); - } -} diff --git a/src/Discord.Net.Rest/Net/Queue/GatewayBucket.cs b/src/Discord.Net.Rest/Net/Queue/GatewayBucket.cs index 65d652656..3de0aac27 100644 --- a/src/Discord.Net.Rest/Net/Queue/GatewayBucket.cs +++ b/src/Discord.Net.Rest/Net/Queue/GatewayBucket.cs @@ -11,32 +11,16 @@ namespace Discord.Net.Queue } internal struct GatewayBucket { - private static ImmutableDictionary DefsByType; - private static ImmutableDictionary DefsById; + private static readonly ImmutableDictionary DefsByType; + private static readonly ImmutableDictionary DefsById; static GatewayBucket() { - SetLimits(GatewayLimits.GetOrCreate(null)); - } - - public static GatewayBucket Get(GatewayBucketType type) => DefsByType[type]; - public static GatewayBucket Get(string id) => DefsById[id]; - - public static void SetLimits(GatewayLimits limits) - { - limits = GatewayLimits.GetOrCreate(limits); - Preconditions.GreaterThan(limits.Global.Count, 0, nameof(limits.Global.Count), "Global count must be greater than zero."); - Preconditions.GreaterThan(limits.Global.Seconds, 0, nameof(limits.Global.Seconds), "Global seconds must be greater than zero."); - Preconditions.GreaterThan(limits.Identify.Count, 0, nameof(limits.Identify.Count), "Identify count must be greater than zero."); - Preconditions.GreaterThan(limits.Identify.Seconds, 0, nameof(limits.Identify.Seconds), "Identify seconds must be greater than zero."); - Preconditions.GreaterThan(limits.PresenceUpdate.Count, 0, nameof(limits.PresenceUpdate.Count), "PresenceUpdate count must be greater than zero."); - Preconditions.GreaterThan(limits.PresenceUpdate.Seconds, 0, nameof(limits.PresenceUpdate.Seconds), "PresenceUpdate seconds must be greater than zero."); - var buckets = new[] { - new GatewayBucket(GatewayBucketType.Unbucketed, "", limits.Global.Count, limits.Global.Seconds), - new GatewayBucket(GatewayBucketType.Identify, "", limits.Identify.Count, limits.Identify.Seconds), - new GatewayBucket(GatewayBucketType.PresenceUpdate, "", limits.Identify.Count, limits.Identify.Seconds), + new GatewayBucket(GatewayBucketType.Unbucketed, "", 120, 60), + new GatewayBucket(GatewayBucketType.Identify, "", 1, 5), + new GatewayBucket(GatewayBucketType.PresenceUpdate, "", 5, 60), }; var builder = ImmutableDictionary.CreateBuilder(); @@ -50,6 +34,9 @@ namespace Discord.Net.Queue DefsById = builder2.ToImmutable(); } + public static GatewayBucket Get(GatewayBucketType type) => DefsByType[type]; + public static GatewayBucket Get(string id) => DefsById[id]; + public GatewayBucketType Type { get; } public string Id { get; } public int WindowCount { get; set; } diff --git a/src/Discord.Net.WebSocket/BaseSocketClient.cs b/src/Discord.Net.WebSocket/BaseSocketClient.cs index 24d574bd4..652654d73 100644 --- a/src/Discord.Net.WebSocket/BaseSocketClient.cs +++ b/src/Discord.Net.WebSocket/BaseSocketClient.cs @@ -80,7 +80,7 @@ namespace Discord.WebSocket internal BaseSocketClient(DiscordSocketConfig config, DiscordRestApiClient client) : base(config, client) => BaseConfig = config; private static DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config) - => new DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config.GatewayLimits, + => new DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config, rateLimitPrecision: config.RateLimitPrecision, useSystemClock: config.UseSystemClock); diff --git a/src/Discord.Net.WebSocket/DiscordShardedClient.cs b/src/Discord.Net.WebSocket/DiscordShardedClient.cs index 3e6b2f024..f759457ca 100644 --- a/src/Discord.Net.WebSocket/DiscordShardedClient.cs +++ b/src/Discord.Net.WebSocket/DiscordShardedClient.cs @@ -6,7 +6,6 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using System.Threading; -using Discord.Net.Queue; namespace Discord.WebSocket { @@ -67,7 +66,6 @@ namespace Discord.WebSocket config.DisplayInitialLog = false; _baseConfig = config; _connectionGroupLock = new SemaphoreSlim(1, 1); - GatewayBucket.SetLimits(GatewayLimits.GetOrCreate(config.GatewayLimits)); if (config.TotalShards == null) _automaticShards = true; @@ -81,15 +79,15 @@ namespace Discord.WebSocket _shardIdsToIndex.Add(_shardIds[i], i); var newConfig = config.Clone(); newConfig.ShardId = _shardIds[i]; - if (config.GatewayLimits.IdentifyMaxConcurrency != 1) - newConfig.GatewayLimits.IdentifySemaphoreName += $"_{i / config.GatewayLimits.IdentifyMaxConcurrency}"; + if (config.IdentifyMaxConcurrency != 1) + newConfig.IdentifySemaphoreName += $"_{i / config.IdentifyMaxConcurrency}"; _shards[i] = new DiscordSocketClient(newConfig, _connectionGroupLock, i != 0 ? _shards[0] : null); RegisterEvents(_shards[i], i == 0); } } } private static API.DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config) - => new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config.GatewayLimits, + => new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config, rateLimitPrecision: config.RateLimitPrecision); internal override async Task OnLoginAsync(TokenType tokenType, string token) @@ -101,7 +99,7 @@ namespace Discord.WebSocket _totalShards = _shardIds.Length; _shards = new DiscordSocketClient[_shardIds.Length]; int maxConcurrency = botGateway.SessionStartLimit.MaxConcurrency; - _baseConfig.GatewayLimits.IdentifyMaxConcurrency = maxConcurrency; + _baseConfig.IdentifyMaxConcurrency = maxConcurrency; for (int i = 0; i < _shardIds.Length; i++) { _shardIdsToIndex.Add(_shardIds[i], i); @@ -109,7 +107,7 @@ namespace Discord.WebSocket newConfig.ShardId = _shardIds[i]; newConfig.TotalShards = _totalShards; if (maxConcurrency != 1) - newConfig.GatewayLimits.IdentifySemaphoreName += $"_{i / maxConcurrency}"; + newConfig.IdentifySemaphoreName += $"_{i / maxConcurrency}"; _shards[i] = new DiscordSocketClient(newConfig, _connectionGroupLock, i != 0 ? _shards[0] : null); RegisterEvents(_shards[i], i == 0); } diff --git a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs index a04ec965e..1193f136d 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketApiClient.cs @@ -38,11 +38,11 @@ namespace Discord.API public ConnectionState ConnectionState { get; private set; } - public DiscordSocketApiClient(RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, string userAgent, GatewayLimits limits, + public DiscordSocketApiClient(RestClientProvider restClientProvider, WebSocketProvider webSocketProvider, string userAgent, DiscordSocketConfig config, string url = null, RetryMode defaultRetryMode = RetryMode.AlwaysRetry, JsonSerializer serializer = null, RateLimitPrecision rateLimitPrecision = RateLimitPrecision.Second, bool useSystemClock = true) - : base(restClientProvider, userAgent, new RequestQueue(limits.IdentifyMasterSemaphoreName, limits.IdentifySemaphoreName, limits.IdentifyMaxConcurrency), defaultRetryMode, serializer, rateLimitPrecision, useSystemClock) + : base(restClientProvider, userAgent, new RequestQueue(config.IdentifyMasterSemaphoreName, config.IdentifySemaphoreName, config.IdentifyMaxConcurrency), defaultRetryMode, serializer, rateLimitPrecision, useSystemClock) { _gatewayUrl = url; if (url != null) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index ac9d8da8e..3a94043a2 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -119,10 +119,7 @@ namespace Discord.WebSocket /// /// The configuration to be used with the client. #pragma warning disable IDISP004 - public DiscordSocketClient(DiscordSocketConfig config) : this(config, CreateApiClient(config), null, null) - { - GatewayBucket.SetLimits(GatewayLimits.GetOrCreate(config.GatewayLimits)); - } + public DiscordSocketClient(DiscordSocketConfig config) : this(config, CreateApiClient(config), null, null) { } internal DiscordSocketClient(DiscordSocketConfig config, SemaphoreSlim groupLock, DiscordSocketClient parentClient) : this(config, CreateApiClient(config), groupLock, parentClient) { } #pragma warning restore IDISP004 private DiscordSocketClient(DiscordSocketConfig config, API.DiscordSocketApiClient client, SemaphoreSlim groupLock, DiscordSocketClient parentClient) @@ -182,7 +179,7 @@ namespace Discord.WebSocket _largeGuilds = new ConcurrentQueue(); } private static API.DiscordSocketApiClient CreateApiClient(DiscordSocketConfig config) - => new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config.GatewayLimits, config.GatewayHost, + => new API.DiscordSocketApiClient(config.RestClientProvider, config.WebSocketProvider, DiscordRestConfig.UserAgent, config, config.GatewayHost, rateLimitPrecision: config.RateLimitPrecision); /// internal override void Dispose(bool disposing) diff --git a/src/Discord.Net.WebSocket/DiscordSocketConfig.cs b/src/Discord.Net.WebSocket/DiscordSocketConfig.cs index 180a8bf49..f59761c26 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketConfig.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketConfig.cs @@ -1,7 +1,7 @@ -using Discord.Net.Queue; using Discord.Net.Udp; using Discord.Net.WebSockets; using Discord.Rest; +using System; namespace Discord.WebSocket { @@ -126,14 +126,32 @@ namespace Discord.WebSocket public bool GuildSubscriptions { get; set; } = true; /// - /// Gets or sets the gateway limits. + /// Gets or sets the name of the master + /// used by identify. /// /// - /// - /// This property should only be changed for bots that have special limits provided by Discord. - /// + /// It is used to define what slave + /// is free to run for concurrent identify requests. /// - public GatewayLimits GatewayLimits { get; set; } = GatewayLimits.Default; + public string IdentifyMasterSemaphoreName { get; set; } = Guid.NewGuid().ToString(); + + /// + /// Gets or sets the name of the slave + /// used by identify. + /// + /// + /// If the maximum concurrency is higher than one and you are using the sharded client, + /// it will be dinamilly renamed to fit the necessary needs. + /// + public string IdentifySemaphoreName { get; set; } = Guid.NewGuid().ToString(); + + /// + /// Gets or sets the maximum identify concurrency. + /// + /// + /// This information is provided by Discord. + /// + public int IdentifyMaxConcurrency { get; set; } = 1; /// /// Initializes a default configuration. @@ -144,11 +162,6 @@ namespace Discord.WebSocket UdpSocketProvider = DefaultUdpSocketProvider.Instance; } - internal DiscordSocketConfig Clone() - { - var clone = MemberwiseClone() as DiscordSocketConfig; - clone.GatewayLimits = GatewayLimits.Clone(); - return clone; - } + internal DiscordSocketConfig Clone() => MemberwiseClone() as DiscordSocketConfig; } }