Skip to content

Commit 81a3cd1

Browse files
authored
Merge pull request AnIdiotsGuide#97 from iAmZiNc/patch-1
Update sharding.md example code
2 parents e469ad9 + fb6b9fa commit 81a3cd1

File tree

1 file changed

+158
-5
lines changed

1 file changed

+158
-5
lines changed

understanding/sharding.md

Lines changed: 158 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,173 @@ You do not need to worry about sharding until your bot hits around 2,400 guilds.
1111
There are additional difficulties when sharding a bot that add complexity to your code \(one of the reasons you shouldn't shard too early\).
1212

1313
* Collections do not cache data from all shards, so you can't grab data from a guild in another shard easily.
14-
* In order to do anything across shards you need to worry about using `broadcastEval` and such \(tutorial coming soon!\).
14+
* In order to do anything across shards you need to worry about using `broadcastEval` and such \(Examples and explanation below\).
1515
* Sharded bots often gain very marginal performance increase and might even use _more_ memory due to using more node processes.
1616
* If you're using any sort of database or connection, multiple shards may cause issues with multiple processes connecting to a single end point.
1717

18-
## Example Sharding Code
18+
## Example Sharding Manager Code
1919

2020
```javascript
2121
/*
2222
The following code goes into it's own file, and you run this file
2323
instead of your main bot file.
2424
*/
2525

26-
const Discord = require('discord.js');
27-
const Manager = new Discord.ShardingManager('./YOUR_BOT_FILE_NAME.js');
28-
Manager.spawn(2); // This example will spawn 2 shards (5,000 guilds);
26+
// Include discord.js ShardingManger
27+
const { ShardingManager } = require('discord.js');
28+
29+
// Create your ShardingManger instance
30+
const manager = new ShardingManager('./YOUR_BOT_FILE_NAME.js', {
31+
// for ShardingManager options see:
32+
// https://discord.js.org/#/docs/main/v11/class/ShardingManager
33+
34+
// 'auto' handles shard count automatically
35+
totalShards: 'auto',
36+
37+
// your bot token
38+
token: 'YOUR_TOKEN_GOES_HERE'
39+
});
40+
41+
// Spawn your shards
42+
manager.spawn();
43+
44+
// The shardCreate event is emitted when a shard is created.
45+
// You can use it for something like logging shard launches.
46+
manager.on('shardCreate', (shard) => console.log(`Shard ${shard.id} launched`));
47+
```
48+
49+
## Sharing Information Between Shards
50+
51+
{% hint style="info" %}
52+
Information is not readily available between shards. In order to get or share information across shards, you will need to make use of either `fetchClientValues()` or `broadcastEval()`.
53+
{% endhint %}
54+
55+
Remember how we were talking about sharding being a method of "splitting" the bot into multiple instances of itself? Because your sharded bot is now in separate, individual instances, things like your adding your total guilds or getting a specific guild are not as simple as they were before. We must now use either [`fetchClientValues`](##FetchClientValues) or [`broadcastEval`](##BroadcastEval) to get information from across shards.
56+
57+
These two functions are your go-to for getting any information from other shards, so get familiar with them!
58+
59+
## FetchClientValues
60+
61+
[`fetchClientValues`](https://discord.js.org/#/docs/main/v11/class/ShardClientUtil?scrollTo=fetchClientValues) gets Client properties from all shards. This is what you should use when you would like to get any of the nested properties of the Client, such as `guilds.size` or `uptime`. It's useful for getting things like Collection sizes, basic client properties, and unprocessed information about the client.
62+
63+
Example:
64+
```javascript
65+
/*
66+
Example result of fetchClientValues() on a bot with 4,300 guilds split across 4 shards.
67+
Assume this is being executed on shard 0, the first shard.
68+
*/
69+
70+
// If we just get our client.guilds.size, it will return
71+
// only the number of guilds on the shard this is being run on.
72+
console.log('client.guilds.size');
73+
// 1050
74+
75+
// If we would like to get our client.guilds.size from all
76+
// of our shards, we must make use of fetchClientValues().
77+
const res = await client.shard.fetchClientValues('guilds.size');
78+
console.log(res);
79+
// [
80+
//1050, // shard 0
81+
//1100, // shard 1
82+
//1075, // shard 2
83+
//1075 // shard 3
84+
//]
85+
86+
````
87+
88+
Let's say you want to do something like get your total server count - In a non-sharded environment, this would be as simple as getting the `client.guilds.size`. However in a sharded environment, `client.guilds.size` will return not the total servers your bot is in. Instead it returns only the total number of servers *on this shard*, like in the first part of the example above.
89+
90+
Here's an example of a function that uses `fetchClientValues()` to first get, then add the total number of guilds from *all shards* (i.e. your bot's total guild count):
91+
92+
```javascript
93+
/*
94+
Example by ZiNc#2032
95+
The following code fetches total combined shards' server counts.
96+
97+
discord.js version 11.x
98+
client = new discordjs.Client()
99+
100+
returns number
101+
*/
102+
103+
const getServerCount = async () => {
104+
// get guild collection size from all the shards
105+
const req = await client.shard.fetchClientValues('guilds.size');
106+
107+
// return the added value
108+
return req.reduce((p, n) => p + n, 0);
109+
}
110+
```
111+
112+
{% hint style="info" %}
113+
`fetchClientValues()` does not allow you to make use of javascript methods or client methods to get or process information before returning it. It only allows you to get information from client properties.
114+
{% endhint %}
115+
116+
## BroacastEval
117+
118+
[`broadcastEval`](https://discord.js.org/#/docs/main/v11/class/ShardClientUtil?scrollTo=broadcastEval) evaluates the input *in the context of each shard's Client(s)* (i.e. `this` is used to reference the `Client`). This is what you should use when you want to execute a method or process data on a shard and return the result. It's useful for getting information that isn't available through client properties and must instead be retrieved through the use of methods.
119+
120+
Example:
121+
```javascript
122+
/*
123+
Example of result of broadcastEval() on a bot with 4 servers split across 2 shards.
124+
Assume this is being executed on shard 0, the first shard.
125+
*/
126+
127+
// If we just map our guilds' members.size, it will return
128+
// only the mapped members.size of the shard this is being run on.
129+
console.log(client.guilds.map((guild) => guild.members.size));
130+
//[
131+
//30,
132+
//25
133+
//],
134+
135+
// If we would like to map our guilds' members.size from our
136+
// servers on all of our shards, we must make use of broadcastEval().
137+
// Remember, this runs in the context of the client, so we refer to the
138+
// Client using "this".
139+
const res = await client.shard.broadcastEval('this.guilds.map((guild) => guild.members.size)');
140+
console.log(res);
141+
// [
142+
//[ // shard 0
143+
//30,
144+
//25
145+
//],
146+
//[ // shard 1
147+
//55,
148+
//10
149+
//]
150+
// ]
151+
152+
````
153+
154+
Say you want to get a guild from your client. In a non-sharded environment, you would simply use `client.guilds.get('ID')` or something of that nature and then carry on with your code. In a sharded environment however, it is possible that the guild you're trying to get *is not present on the shard*. In order to get the guild for use, you would then need to fetch it from whatever shard it is present on using `broadcastEval()`.
155+
156+
Here's an example of a function that uses `broadcastEval()` to get a single guild no matter what shard it is present on:
157+
158+
```javascript
159+
/*
160+
Example by ZiNc#2032
161+
The following code fetches a single guild from across shards.
162+
163+
NOTE: Fetched guild's properties such as "Guild.members" and "Guild.roles" will
164+
not be Managers; these properties will be arrays of snowflake IDs.
165+
166+
discord.js version 11.x
167+
client = new discordjs.Client()
168+
169+
returns Guild
170+
*/
171+
172+
const getServer = async (guildID) => {
173+
// try to get guild from all the shards
174+
const req = await client.shard.broadcastEval(`this.guilds.get("${guildID}")`);
175+
176+
// return non-null response or false if not found
177+
return (req.find((res) => !!res) || false);
178+
}
29179
```
30180

181+
{% hint style="info" %}
182+
`broadcastEval()` will only return basic javascript objects, and will not return Discord.js structures such as Collections, Guild objects, Member object, and the likes. You will need to interact directly with the API or build these structures yourself after getting a response back from your `broadcastEval()`.
183+
{% endhint %}

0 commit comments

Comments
 (0)