diff options
Diffstat (limited to 'node_modules/discord.js/src/sharding')
| -rw-r--r-- | node_modules/discord.js/src/sharding/Shard.js | 164 | ||||
| -rw-r--r-- | node_modules/discord.js/src/sharding/ShardClientUtil.js | 143 | ||||
| -rw-r--r-- | node_modules/discord.js/src/sharding/ShardingManager.js | 193 |
3 files changed, 0 insertions, 500 deletions
diff --git a/node_modules/discord.js/src/sharding/Shard.js b/node_modules/discord.js/src/sharding/Shard.js deleted file mode 100644 index ab9b923..0000000 --- a/node_modules/discord.js/src/sharding/Shard.js +++ /dev/null @@ -1,164 +0,0 @@ -const childProcess = require('child_process'); -const path = require('path'); -const makeError = require('../util/MakeError'); -const makePlainError = require('../util/MakePlainError'); - -/** - * Represents a Shard spawned by the ShardingManager. - */ -class Shard { - /** - * @param {ShardingManager} manager The sharding manager - * @param {number} id The ID of this shard - * @param {Array} [args=[]] Command line arguments to pass to the script - */ - constructor(manager, id, args = []) { - /** - * Manager that created the shard - * @type {ShardingManager} - */ - this.manager = manager; - - /** - * ID of the shard - * @type {number} - */ - this.id = id; - - /** - * The environment variables for the shard - * @type {Object} - */ - this.env = Object.assign({}, process.env, { - SHARD_ID: this.id, - SHARD_COUNT: this.manager.totalShards, - CLIENT_TOKEN: this.manager.token, - }); - - /** - * Process of the shard - * @type {ChildProcess} - */ - this.process = childProcess.fork(path.resolve(this.manager.file), args, { - env: this.env, - }); - this.process.on('message', this._handleMessage.bind(this)); - this.process.once('exit', () => { - if (this.manager.respawn) this.manager.createShard(this.id); - }); - - this._evals = new Map(); - this._fetches = new Map(); - } - - /** - * Sends a message to the shard's process. - * @param {*} message Message to send to the shard - * @returns {Promise<Shard>} - */ - send(message) { - return new Promise((resolve, reject) => { - const sent = this.process.send(message, err => { - if (err) reject(err); else resolve(this); - }); - if (!sent) throw new Error('Failed to send message to shard\'s process.'); - }); - } - - /** - * Fetches a Client property value of the shard. - * @param {string} prop Name of the Client property to get, using periods for nesting - * @returns {Promise<*>} - * @example - * shard.fetchClientValue('guilds.size').then(count => { - * console.log(`${count} guilds in shard ${shard.id}`); - * }).catch(console.error); - */ - fetchClientValue(prop) { - if (this._fetches.has(prop)) return this._fetches.get(prop); - - const promise = new Promise((resolve, reject) => { - const listener = message => { - if (!message || message._fetchProp !== prop) return; - this.process.removeListener('message', listener); - this._fetches.delete(prop); - resolve(message._result); - }; - this.process.on('message', listener); - - this.send({ _fetchProp: prop }).catch(err => { - this.process.removeListener('message', listener); - this._fetches.delete(prop); - reject(err); - }); - }); - - this._fetches.set(prop, promise); - return promise; - } - - /** - * Evaluates a script on the shard, in the context of the Client. - * @param {string} script JavaScript to run on the shard - * @returns {Promise<*>} Result of the script execution - */ - eval(script) { - if (this._evals.has(script)) return this._evals.get(script); - - const promise = new Promise((resolve, reject) => { - const listener = message => { - if (!message || message._eval !== script) return; - this.process.removeListener('message', listener); - this._evals.delete(script); - if (!message._error) resolve(message._result); else reject(makeError(message._error)); - }; - this.process.on('message', listener); - - this.send({ _eval: script }).catch(err => { - this.process.removeListener('message', listener); - this._evals.delete(script); - reject(err); - }); - }); - - this._evals.set(script, promise); - return promise; - } - - /** - * Handles an IPC message - * @param {*} message Message received - * @private - */ - _handleMessage(message) { - if (message) { - // Shard is requesting a property fetch - if (message._sFetchProp) { - this.manager.fetchClientValues(message._sFetchProp).then( - results => this.send({ _sFetchProp: message._sFetchProp, _result: results }), - err => this.send({ _sFetchProp: message._sFetchProp, _error: makePlainError(err) }) - ); - return; - } - - // Shard is requesting an eval broadcast - if (message._sEval) { - this.manager.broadcastEval(message._sEval).then( - results => this.send({ _sEval: message._sEval, _result: results }), - err => this.send({ _sEval: message._sEval, _error: makePlainError(err) }) - ); - return; - } - } - - /** - * Emitted upon recieving a message from a shard - * @event ShardingManager#message - * @param {Shard} shard Shard that sent the message - * @param {*} message Message that was received - */ - this.manager.emit('message', this, message); - } -} - -module.exports = Shard; diff --git a/node_modules/discord.js/src/sharding/ShardClientUtil.js b/node_modules/discord.js/src/sharding/ShardClientUtil.js deleted file mode 100644 index 6449941..0000000 --- a/node_modules/discord.js/src/sharding/ShardClientUtil.js +++ /dev/null @@ -1,143 +0,0 @@ -const makeError = require('../util/MakeError'); -const makePlainError = require('../util/MakePlainError'); - -/** - * Helper class for sharded clients spawned as a child process, such as from a ShardingManager - */ -class ShardClientUtil { - /** - * @param {Client} client Client of the current shard - */ - constructor(client) { - this.client = client; - process.on('message', this._handleMessage.bind(this)); - } - - /** - * ID of this shard - * @type {number} - * @readonly - */ - get id() { - return this.client.options.shardId; - } - - /** - * Total number of shards - * @type {number} - * @readonly - */ - get count() { - return this.client.options.shardCount; - } - - /** - * Sends a message to the master process - * @param {*} message Message to send - * @returns {Promise<void>} - */ - send(message) { - return new Promise((resolve, reject) => { - const sent = process.send(message, err => { - if (err) reject(err); else resolve(); - }); - if (!sent) throw new Error('Failed to send message to master process.'); - }); - } - - /** - * Fetches a Client property value of each shard. - * @param {string} prop Name of the Client property to get, using periods for nesting - * @returns {Promise<Array>} - * @example - * client.shard.fetchClientValues('guilds.size').then(results => { - * console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`); - * }).catch(console.error); - */ - fetchClientValues(prop) { - return new Promise((resolve, reject) => { - const listener = message => { - if (!message || message._sFetchProp !== prop) return; - process.removeListener('message', listener); - if (!message._error) resolve(message._result); else reject(makeError(message._error)); - }; - process.on('message', listener); - - this.send({ _sFetchProp: prop }).catch(err => { - process.removeListener('message', listener); - reject(err); - }); - }); - } - - /** - * Evaluates a script on all shards, in the context of the Clients. - * @param {string} script JavaScript to run on each shard - * @returns {Promise<Array>} Results of the script execution - */ - broadcastEval(script) { - return new Promise((resolve, reject) => { - const listener = message => { - if (!message || message._sEval !== script) return; - process.removeListener('message', listener); - if (!message._error) resolve(message._result); else reject(makeError(message._error)); - }; - process.on('message', listener); - - this.send({ _sEval: script }).catch(err => { - process.removeListener('message', listener); - reject(err); - }); - }); - } - - /** - * Handles an IPC message - * @param {*} message Message received - * @private - */ - _handleMessage(message) { - if (!message) return; - if (message._fetchProp) { - const props = message._fetchProp.split('.'); - let value = this.client; - for (const prop of props) value = value[prop]; - this._respond('fetchProp', { _fetchProp: message._fetchProp, _result: value }); - } else if (message._eval) { - try { - this._respond('eval', { _eval: message._eval, _result: this.client._eval(message._eval) }); - } catch (err) { - this._respond('eval', { _eval: message._eval, _error: makePlainError(err) }); - } - } - } - - /** - * Sends a message to the master process, emitting an error from the client upon failure - * @param {string} type Type of response to send - * @param {*} message Message to send - * @private - */ - _respond(type, message) { - this.send(message).catch(err => { - err.message = `Error when sending ${type} response to master process: ${err.message}`; - this.client.emit('error', err); - }); - } - - /** - * Creates/gets the singleton of this class - * @param {Client} client Client to use - * @returns {ShardClientUtil} - */ - static singleton(client) { - if (!this._singleton) { - this._singleton = new this(client); - } else { - client.emit('warn', 'Multiple clients created in child process; only the first will handle sharding helpers.'); - } - return this._singleton; - } -} - -module.exports = ShardClientUtil; diff --git a/node_modules/discord.js/src/sharding/ShardingManager.js b/node_modules/discord.js/src/sharding/ShardingManager.js deleted file mode 100644 index 671b5d7..0000000 --- a/node_modules/discord.js/src/sharding/ShardingManager.js +++ /dev/null @@ -1,193 +0,0 @@ -const path = require('path'); -const fs = require('fs'); -const EventEmitter = require('events').EventEmitter; -const mergeDefault = require('../util/MergeDefault'); -const Shard = require('./Shard'); -const Collection = require('../util/Collection'); -const fetchRecommendedShards = require('../util/FetchRecommendedShards'); - -/** - * This is a utility class that can be used to help you spawn shards of your Client. Each shard is completely separate - * from the other. The Shard Manager takes a path to a file and spawns it under the specified amount of shards safely. - * If you do not select an amount of shards, the manager will automatically decide the best amount. - * @extends {EventEmitter} - */ -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 {boolean} [options.respawn=true] Whether shards should automatically respawn upon exiting - * @param {string[]} [options.shardArgs=[]] Arguments to pass to the shard script when spawning - * @param {string} [options.token] Token to use for automatic shard count and passing to shards - */ - constructor(file, options = {}) { - super(); - options = mergeDefault({ - totalShards: 'auto', - respawn: true, - shardArgs: [], - token: null, - }, options); - - /** - * Path to the shard script file - * @type {string} - */ - this.file = file; - if (!file) throw new Error('File must be specified.'); - if (!path.isAbsolute(file)) this.file = path.resolve(process.cwd(), file); - const stats = fs.statSync(this.file); - if (!stats.isFile()) throw new Error('File path does not point to a file.'); - - /** - * Amount of shards that this manager is going to spawn - * @type {number|string} - */ - this.totalShards = options.totalShards; - if (this.totalShards !== 'auto') { - if (typeof this.totalShards !== 'number' || isNaN(this.totalShards)) { - throw new TypeError('Amount of shards must be a number.'); - } - if (this.totalShards < 1) throw new RangeError('Amount of shards must be at least 1.'); - if (this.totalShards !== Math.floor(this.totalShards)) { - throw new RangeError('Amount of shards must be an integer.'); - } - } - - /** - * Whether shards should automatically respawn upon exiting - * @type {boolean} - */ - this.respawn = options.respawn; - - /** - * An array of arguments to pass to shards. - * @type {string[]} - */ - this.shardArgs = options.shardArgs; - - /** - * Token to use for obtaining the automatic shard count, and passing to shards - * @type {?string} - */ - this.token = options.token ? options.token.replace(/^Bot\s*/i, '') : null; - - /** - * A collection of shards that this manager has spawned - * @type {Collection<number, Shard>} - */ - this.shards = new Collection(); - } - - /** - * Spawns a single shard. - * @param {number} id The ID of the shard to spawn. **This is usually not necessary.** - * @returns {Promise<Shard>} - */ - createShard(id = this.shards.size) { - const shard = new Shard(this, id, this.shardArgs); - this.shards.set(id, shard); - /** - * Emitted upon launching a shard - * @event ShardingManager#launch - * @param {Shard} shard Shard that was launched - */ - this.emit('launch', shard); - return Promise.resolve(shard); - } - - /** - * Spawns multiple shards. - * @param {number} [amount=this.totalShards] Number of shards to spawn - * @param {number} [delay=5500] How long to wait in between spawning each shard (in milliseconds) - * @returns {Promise<Collection<number, Shard>>} - */ - spawn(amount = this.totalShards, delay = 5500) { - if (amount === 'auto') { - return fetchRecommendedShards(this.token).then(count => { - this.totalShards = count; - return this._spawn(count, delay); - }); - } else { - if (typeof amount !== 'number' || isNaN(amount)) throw new TypeError('Amount of shards must be a number.'); - if (amount < 1) throw new RangeError('Amount of shards must be at least 1.'); - if (amount !== Math.floor(amount)) throw new TypeError('Amount of shards must be an integer.'); - return this._spawn(amount, delay); - } - } - - /** - * Actually spawns shards, unlike that poser above >:( - * @param {number} amount Number of shards to spawn - * @param {number} delay How long to wait in between spawning each shard (in milliseconds) - * @returns {Promise<Collection<number, Shard>>} - * @private - */ - _spawn(amount, delay) { - return new Promise(resolve => { - if (this.shards.size >= amount) throw new Error(`Already spawned ${this.shards.size} shards.`); - this.totalShards = amount; - - this.createShard(); - if (this.shards.size >= this.totalShards) { - resolve(this.shards); - return; - } - - if (delay <= 0) { - while (this.shards.size < this.totalShards) this.createShard(); - resolve(this.shards); - } else { - const interval = setInterval(() => { - this.createShard(); - if (this.shards.size >= this.totalShards) { - clearInterval(interval); - resolve(this.shards); - } - }, delay); - } - }); - } - - /** - * Send a message to all shards. - * @param {*} message Message to be sent to the shards - * @returns {Promise<Shard[]>} - */ - broadcast(message) { - const promises = []; - for (const shard of this.shards.values()) promises.push(shard.send(message)); - return Promise.all(promises); - } - - /** - * Evaluates a script on all shards, in the context of the Clients. - * @param {string} script JavaScript to run on each shard - * @returns {Promise<Array>} Results of the script execution - */ - broadcastEval(script) { - const promises = []; - for (const shard of this.shards.values()) promises.push(shard.eval(script)); - return Promise.all(promises); - } - - /** - * Fetches a Client property value of each shard. - * @param {string} prop Name of the Client property to get, using periods for nesting - * @returns {Promise<Array>} - * @example - * manager.fetchClientValues('guilds.size').then(results => { - * console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`); - * }).catch(console.error); - */ - fetchClientValues(prop) { - if (this.shards.size === 0) return Promise.reject(new Error('No shards have been spawned.')); - if (this.shards.size !== this.totalShards) return Promise.reject(new Error('Still spawning shards.')); - const promises = []; - for (const shard of this.shards.values()) promises.push(shard.fetchClientValue(prop)); - return Promise.all(promises); - } -} - -module.exports = ShardingManager; |
