mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-15 11:03:30 +01:00
feat: Internal sharding (#2902)
* internal sharding * ready event * the square deal * the new deal * the second new deal * add actual documentation * the new freedom * the great society * federal intervention * some of requested changes * i ran out of things to call these * destroy this * fix: Client#uptime went missing * fix(Client): destroy the client on login failure This may happen duo invalid sharding config / invalid token / user requested destroy * fix(Client): reject login promise when the client is destroyed before ready * fix(WebSocketManager): remove redundancy in destroy method (#2491) * typo(ErrorMessages): duo -> duo to * typo(ErrorMessages): duo -> due * fix: docs and options * docs(WebSocketManager): WebSockethard -> WebSocketShard (#2502) * fix(ClientUser): lazily load to account for extended user structure (#2501) * docs(WebSocketShard): document class to make it visible in documentation (#2504) * fix: WebSocketShard#reconnect * fix: presenceUpdate & userUpdate * presenceUpdate wasn't really being handled at all * userUpdate handled incorrectly because as of v7 in the Discord API, it comes inside presenceUpdate * re-add raw event * member is now part of message create payload * feat: Add functionality to support multiple servers with different shards (#2395) * Added functionallity to spawn multiple sharding managers due to adding start and end shards * Small fixes and limiting shard amount to max recommended * Forgot a check in spawn() * Fixed indentation * Removed optiosn object documentation for totalShards * More fixes and a check that the startShard + amount doesnt go over the recommended shard amount * fix getting max recommended * Removed async from constructor (my fault) * Changed start and end shard to a shardList or "auto" + fixed some brainfarts with isNaN * Changed the loop and totalShard count calculation * shards are actually 0 based * Fixed a problem with the gateway and handled some range errors and type errors * Changed Number.isNan to isNaN and changed a few Integer checks to use Number.isInteger * Added check if shardList contains smth greater than totalShards; made spawn use totalShards again; shardList will be ignored and rebuild if totalShards is 'auto'; fixed docs * ShardingManager#spawn now uses a for..of loop; fixed the if statement inside the new for..of loop to still work as intended; made the totalShards be set to a new amount if smth manual is put into ShardingManager#spawn just like before; Fixed some spelling * internal sharding * ready event * the square deal * the new deal * the second new deal * add actual documentation * the new freedom * the great society * federal intervention * some of requested changes * i ran out of things to call these * destroy this * fix: Client#uptime went missing * fix(Client): destroy the client on login failure This may happen duo invalid sharding config / invalid token / user requested destroy * fix(Client): reject login promise when the client is destroyed before ready * fix(WebSocketManager): remove redundancy in destroy method (#2491) * typo(ErrorMessages): duo -> duo to * typo(ErrorMessages): duo -> due * fix: docs and options * docs(WebSocketManager): WebSockethard -> WebSocketShard (#2502) * fix(ClientUser): lazily load to account for extended user structure (#2501) * docs(WebSocketShard): document class to make it visible in documentation (#2504) * fix: WebSocketShard#reconnect * fix: presenceUpdate & userUpdate * presenceUpdate wasn't really being handled at all * userUpdate handled incorrectly because as of v7 in the Discord API, it comes inside presenceUpdate * Internal Sharding adaptation Adapted to internal sharding Fixed a bug where non ready invalidated sessions wouldnt respawn * Fixed shardCount not retrieving * Fixing style removed unnecessary parenthesis * Fixing and rebasing lets hope i didnt dun hecklered it * Fixing my own retardation * Thanks git rebase * fix: assigning member in message create payload * fix: resumes * fix: IS wont give up reconnecting now * docs: add missing docs mostly * fix: found lost methods * fix: WebSocketManager#broadcast check if shard exists * fix: ShardClientUtil#id returning undefined * feat: handle new session rate limits (#2796) * feat: handle new session rate limits * i have no idea what i was doing last night * fix if statement weirdness * fix: re-add presence parsing from ClientOptions (#2893) * resolve conflicts * typings: missing typings * re-add missing linter rule * fix: replacing ClientUser wrongly * address unecessary performance waste * docs: missing disconnect event * fix(typings): Fix 2 issues with typings (#2909) * (Typings) Update typings to reflect current ClientOptions * fix(Typings) fixes a bug with Websockets and DOM Types * fix travis * feat: allow setting presence per shard * add WebSocketManager#shardX events * adjust typings, docs and performance issues * readjust shard events, now provide shardId parameter instead * fix: ready event should check shardCount, not actualShardCount * fix: re-add replayed parameter of Client#resume * fix(Sharding): fixes several things in Internal Sharding (#2914) * fix(Sharding) fixes several things in Internal Sharding * add default value for shards property * better implement checking for shards array * fix travis & some casing * split shard count into 2 words * update to latest Internal Sharding, fix requested changes * make sure totalShardCount is a number * fix comment * fix small typo * dynamically set totalShardCount if either shards or shardCount is provided * consistency: rename shardID to shardId * remove Client#shardIds * fix: typo in GuildIntegrationsUpdate handler * fix: incorrect packet data being passed in some events (#2919) * fix: edgecase of ShardingManager and totalShardCount (#2918) * fix: Client#userUpdate being passed wrong parameter and fix a potential edgecase of returning null in ClientUser#edit from this event * fix consistency and typings issues * consistency: shardId instances renamed to shardID * typings: fix typings regarding WebSocket * style(.eslintrc): remove additional whitespace * fix(Client): remove ondisconnect handler on timeout * docs(BaseClient): fix typo of Immediate * nitpick: typings, private fields and methods * typo: improve grammar a bit * fix: error assigning client in WebSocketManager * typo: actually spell milliseconds properly
This commit is contained in:
@@ -27,7 +27,8 @@ class ShardingManager extends EventEmitter {
|
||||
/**
|
||||
* @param {string} file Path to your shard script file
|
||||
* @param {Object} [options] Options for the sharding manager
|
||||
* @param {number|string} [options.totalShards='auto'] Number of shards to spawn, or "auto"
|
||||
* @param {string|number[]} [options.totalShards='auto'] Number of total shards of all shard managers or "auto"
|
||||
* @param {string|number[]} [options.shardList='auto'] List of shards to spawn or "auto"
|
||||
* @param {ShardingManagerMode} [options.mode='process'] Which mode to use for shards
|
||||
* @param {boolean} [options.respawn=true] Whether shards should automatically respawn upon exiting
|
||||
* @param {string[]} [options.shardArgs=[]] Arguments to pass to the shard script when spawning
|
||||
@@ -58,16 +59,33 @@ class ShardingManager extends EventEmitter {
|
||||
if (!stats.isFile()) throw new Error('CLIENT_INVALID_OPTION', 'File', 'a file');
|
||||
|
||||
/**
|
||||
* Amount of shards that this manager is going to spawn
|
||||
* @type {number|string}
|
||||
* List of shards this sharding manager spawns
|
||||
* @type {string|number[]}
|
||||
*/
|
||||
this.totalShards = options.totalShards;
|
||||
this.shardList = options.shardList || 'auto';
|
||||
if (this.shardList !== 'auto') {
|
||||
if (!Array.isArray(this.shardList)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array.');
|
||||
}
|
||||
this.shardList = [...new Set(this.shardList)];
|
||||
if (this.shardList.length < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'shardList', 'at least 1 ID.');
|
||||
if (this.shardList.some(shardID => typeof shardID !== 'number' || isNaN(shardID) ||
|
||||
!Number.isInteger(shardID) || shardID < 0)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array of postive integers.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Amount of shards that all sharding managers spawn in total
|
||||
* @type {number}
|
||||
*/
|
||||
this.totalShards = options.totalShards || 'auto';
|
||||
if (this.totalShards !== 'auto') {
|
||||
if (typeof this.totalShards !== 'number' || isNaN(this.totalShards)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'a number.');
|
||||
}
|
||||
if (this.totalShards < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'at least 1.');
|
||||
if (this.totalShards !== Math.floor(this.totalShards)) {
|
||||
if (!Number.isInteger(this.totalShards)) {
|
||||
throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'an integer.');
|
||||
}
|
||||
}
|
||||
@@ -150,21 +168,31 @@ class ShardingManager extends EventEmitter {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'a number.');
|
||||
}
|
||||
if (amount < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'at least 1.');
|
||||
if (amount !== Math.floor(amount)) {
|
||||
if (!Number.isInteger(amount)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'an integer.');
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure this many shards haven't already been spawned
|
||||
if (this.shards.size >= amount) throw new Error('SHARDING_ALREADY_SPAWNED', this.shards.size);
|
||||
this.totalShards = amount;
|
||||
if (this.shardList === 'auto' || this.totalShards === 'auto' || this.totalShards !== amount) {
|
||||
this.shardList = [...Array(amount).keys()];
|
||||
}
|
||||
if (this.totalShards === 'auto' || this.totalShards !== amount) {
|
||||
this.totalShards = amount;
|
||||
}
|
||||
|
||||
if (this.shardList.some(shardID => shardID >= amount)) {
|
||||
throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards',
|
||||
'bigger than the highest shardID in the shardList option.');
|
||||
}
|
||||
|
||||
// Spawn the shards
|
||||
for (let s = 1; s <= amount; s++) {
|
||||
for (const shardID of this.shardList) {
|
||||
const promises = [];
|
||||
const shard = this.createShard();
|
||||
const shard = this.createShard(shardID);
|
||||
promises.push(shard.spawn(waitForReady));
|
||||
if (delay > 0 && s !== amount) promises.push(Util.delayFor(delay));
|
||||
if (delay > 0 && this.shards.size !== this.shardList.length - 1) promises.push(Util.delayFor(delay));
|
||||
await Promise.all(promises); // eslint-disable-line no-await-in-loop
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user