diff --git a/Documentation/guides/basic-concepts/Sharding/Program.cs b/Documentation/guides/basic-concepts/Sharding/Program.cs index 1f794e5b..c880bfcc 100644 --- a/Documentation/guides/basic-concepts/Sharding/Program.cs +++ b/Documentation/guides/basic-concepts/Sharding/Program.cs @@ -1,13 +1,13 @@ using NetCord; using NetCord.Gateway; -ShardedGatewayClient shardedGatewayClient = new(new BotToken("Token from Discord Developer Portal")); +ShardedGatewayClient client = new(new BotToken("Token from Discord Developer Portal")); -shardedGatewayClient.Log += (client, message) => +client.Log += (client, message) => { Console.WriteLine($"#{client.Shard.GetValueOrDefault().Id}\t{message}"); return default; }; -await shardedGatewayClient.StartAsync(); +await client.StartAsync(); await Task.Delay(-1); diff --git a/Documentation/guides/basic-concepts/Sharding/RegisteringHandlers.cs b/Documentation/guides/basic-concepts/Sharding/RegisteringHandlers.cs new file mode 100644 index 00000000..36a292c2 --- /dev/null +++ b/Documentation/guides/basic-concepts/Sharding/RegisteringHandlers.cs @@ -0,0 +1,26 @@ +using NetCord; +using NetCord.Gateway; + +namespace MyBot; + +internal class RegisteringHandlers +{ + public static async Task RegisterHandlersAsync() + { + ShardedGatewayClient client = new(new BotToken("Token from Discord Developer Portal")); + + client.Log += (client, message) => + { + Console.WriteLine($"#{client.Shard.GetValueOrDefault().Id}\t{message}"); + return default; + }; + + client.MessageUpdate += async (client, message) => + { + await message.ReplyAsync("Message updated!"); + }; + + await client.StartAsync(); + await Task.Delay(-1); + } +} diff --git a/Documentation/guides/basic-concepts/ShardingHosting/MessageUpdateHandler.cs b/Documentation/guides/basic-concepts/ShardingHosting/MessageUpdateHandler.cs new file mode 100644 index 00000000..3282efea --- /dev/null +++ b/Documentation/guides/basic-concepts/ShardingHosting/MessageUpdateHandler.cs @@ -0,0 +1,13 @@ +using NetCord.Gateway; +using NetCord.Hosting.Gateway; + +namespace MyBot; + +[GatewayEvent(nameof(GatewayClient.MessageUpdate))] +public class MessageUpdateHandler : IShardedGatewayEventHandler +{ + public async ValueTask HandleAsync(GatewayClient client, Message message) + { + await message.ReplyAsync("Message updated!"); + } +} diff --git a/Documentation/guides/basic-concepts/ShardingHosting/RegisteringHandlers.cs b/Documentation/guides/basic-concepts/ShardingHosting/RegisteringHandlers.cs new file mode 100644 index 00000000..13bee2ba --- /dev/null +++ b/Documentation/guides/basic-concepts/ShardingHosting/RegisteringHandlers.cs @@ -0,0 +1,28 @@ +using Microsoft.Extensions.Hosting; + +using NetCord.Gateway; +using NetCord.Hosting.Gateway; + +namespace MyBot; + +internal class RegisteringHandlers +{ + public static async Task RegisterHandlersAsync(string[] args) + { + var builder = Host.CreateApplicationBuilder(args); + + builder.Services + .AddDiscordShardedGateway(options => + { + options.Intents = GatewayIntents.GuildMessages + | GatewayIntents.DirectMessages + | GatewayIntents.MessageContent; + }) + .AddShardedGatewayEventHandlers(typeof(Program).Assembly); + + var host = builder.Build() + .UseShardedGatewayEventHandlers(); + + await host.RunAsync(); + } +} diff --git a/Documentation/guides/basic-concepts/sharding.md b/Documentation/guides/basic-concepts/sharding.md index 4d1cdfcb..2f444857 100644 --- a/Documentation/guides/basic-concepts/sharding.md +++ b/Documentation/guides/basic-concepts/sharding.md @@ -1,25 +1,44 @@ -# Sharding +--- +uid: sharding +omitAppTitle: true +title: Scale Your C# Discord Bot with Sharding in NetCord +description: Implement sharding for your C# Discord bot with NetCord to improve scalability and performance by distributing tasks across multiple gateway connections. +--- -## When to shard? +# Sharding -Sharding is required when your bot is in more than 2500 guilds. +Sharding allows your bot to split its responsibilities across multiple gateway connections. In NetCord, this is managed by the @NetCord.Gateway.ShardedGatewayClient, which acts as a controller for multiple instances of @NetCord.Gateway.GatewayClient. Each shard, represented by a @NetCord.Gateway.GatewayClient, handles a specific subset of guilds. -## What is sharding? +## When to Shard -Sharding is splitting your bot into multiple @"NetCord.Gateway.GatewayClient"s. Each shard, represented as a @NetCord.Gateway.GatewayClient instance, will be responsible for a certain number of guilds. +Sharding becomes necessary when your bot exceeds 2,500 guilds. However, it's recommended to implement sharding earlier, typically when targeting 1,000+ guilds, to ensure smoother scaling and performance. -## How to shard? +## How to Shard -## [.NET Generic Host](#tab/generic-host) +### [.NET Generic Host](#tab/generic-host) -To start sharding with the .NET Generic Host, instead of calling @NetCord.Hosting.Gateway.GatewayClientServiceCollectionExtensions.AddDiscordGateway(Microsoft.Extensions.DependencyInjection.IServiceCollection), you need to call @NetCord.Hosting.Gateway.ShardedGatewayClientServiceCollectionExtensions.AddDiscordShardedGateway(Microsoft.Extensions.DependencyInjection.IServiceCollection). Example: +When using the .NET Generic Host, you can add the @NetCord.Gateway.ShardedGatewayClient by calling @NetCord.Hosting.Gateway.ShardedGatewayClientServiceCollectionExtensions.AddDiscordShardedGateway*. [!code-cs[Program.cs](ShardingHosting/Program.cs)] -Also note that you need to use @NetCord.Hosting.Gateway.IShardedGatewayEventHandler or @NetCord.Hosting.Gateway.IShardedGatewayEventHandler`1 instead of @NetCord.Hosting.Gateway.IGatewayEventHandler or @NetCord.Hosting.Gateway.IGatewayEventHandler`1 for event handlers. You also need to use @NetCord.Hosting.Gateway.GatewayEventHandlerServiceCollectionExtensions.AddShardedGatewayEventHandlers(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Reflection.Assembly) to add event handlers and @NetCord.Hosting.Gateway.GatewayEventHandlerHostExtensions.UseShardedGatewayEventHandlers(Microsoft.Extensions.Hosting.IHost) to bind them. - -## [Bare Bones](#tab/bare-bones) +### [Bare Bones](#tab/bare-bones) -To start sharding, you need to create an instance of @NetCord.Gateway.ShardedGatewayClient. Its usage is very similar to @NetCord.Gateway.GatewayClient. Example: +For a bare-bones setup, you need to manually create an instance of @NetCord.Gateway.ShardedGatewayClient. Its API is very similar to @NetCord.Gateway.GatewayClient. Here's an example: [!code-cs[Program.cs](Sharding/Program.cs)] -As you can see, the only difference in usage is that each event has an additional parameter, which is the @NetCord.Gateway.GatewayClient the event has been received from. Also note that events can be invoked concurrently from different shards. +*** + +## How to Register Events + +### [.NET Generic Host](#tab/generic-host) + +To register event handlers with sharding in the .NET Generic Host, use @NetCord.Hosting.Gateway.GatewayEventHandlerServiceCollectionExtensions.AddShardedGatewayEventHandlers* to add all event handlers in an assembly and then call @NetCord.Hosting.Gateway.GatewayEventHandlerServiceCollectionExtensions.AddShardedGatewayEventHandlers* to bind these handlers to the sharded client. + +[!code-cs[Program.cs](ShardingHosting/RegisteringHandlers.cs?highlight=10,13#L12-L26)] + +When creating event handlers, implement @NetCord.Hosting.Gateway.IShardedGatewayEventHandler or @NetCord.Hosting.Gateway.IShardedGatewayEventHandler`1. Note the additional parameter representing the @NetCord.Gateway.GatewayClient that received the event. +[!code-cs[Program.cs](ShardingHosting/MessageUpdateHandler.cs)] + +### [Bare Bones](#tab/bare-bones) + +For bare-bones setups, adding event handlers is straightforward. Each handler has an additional parameter for the @NetCord.Gateway.GatewayClient that received the event. +[!code-cs[Program.cs](Sharding/RegisteringHandlers.cs#L18-L21)] diff --git a/Documentation/guides/events/first-events.md b/Documentation/guides/events/first-events.md index 144724a0..49118b0c 100644 --- a/Documentation/guides/events/first-events.md +++ b/Documentation/guides/events/first-events.md @@ -26,7 +26,7 @@ When you run this code, when someone reacts to a message, the bot will notify ev Other events work similar to these. You can play with them if you want! > [!NOTE] -> When using @NetCord.Gateway.ShardedGatewayClient, you need to implement @NetCord.Hosting.Gateway.IShardedGatewayEventHandler or @NetCord.Hosting.Gateway.IShardedGatewayEventHandler`1 instead. You also need to use @NetCord.Hosting.Gateway.GatewayEventHandlerServiceCollectionExtensions.AddShardedGatewayEventHandlers(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Reflection.Assembly) to add event handlers and @NetCord.Hosting.Gateway.GatewayEventHandlerHostExtensions.UseShardedGatewayEventHandlers(Microsoft.Extensions.Hosting.IHost) to bind them instead. +> When using @NetCord.Gateway.ShardedGatewayClient, you need to implement @NetCord.Hosting.Gateway.IShardedGatewayEventHandler or @NetCord.Hosting.Gateway.IShardedGatewayEventHandler`1 instead. You also need to use @NetCord.Hosting.Gateway.GatewayEventHandlerServiceCollectionExtensions.AddShardedGatewayEventHandlers* to add event handlers and @NetCord.Hosting.Gateway.GatewayEventHandlerHostExtensions.UseShardedGatewayEventHandlers* to bind them instead. See @sharding?text=Sharding for more information. ## [Bare Bones](#tab/bare-bones)