mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
feat(Sharding*): contexts for broadcastEval (#5756)
* feat(ShardClientUtil): add parameterList to broadcastEval * feat(ShardingManager): add parameterList to broadcastEval * chore: update typings * refactor(Sharding*): use BroadcastEvalOptions * chore: update typings * docs: use serializable instead of stringifiable * refactor: don't set broadcastEval default context Co-authored-by: Antonio Román <kyradiscord@gmail.com> * chore: fix inaccuracy in typings * refactor(Sharding*): remove string-based broadcastEval * fix(ShardingManager): incorrect usage of _broadcastEvalRaw * refactor(ShardingManager): remove unnecessary method * refactor(Sharding*): type check the eval script * fix(ShardingManager): return Promise rejection rather than throwing an error Co-authored-by: SpaceEEC <spaceeec@yahoo.com> * chore: fix typings Co-authored-by: SpaceEEC <spaceeec@yahoo.com> Co-authored-by: Antonio Román <kyradiscord@gmail.com> Co-authored-by: SpaceEEC <spaceeec@yahoo.com>
This commit is contained in:
@@ -24,6 +24,7 @@ const Messages = {
|
||||
DISALLOWED_INTENTS: 'Privileged intent provided is not enabled or whitelisted.',
|
||||
SHARDING_NO_SHARDS: 'No shards have been spawned.',
|
||||
SHARDING_IN_PROCESS: 'Shards are still being spawned.',
|
||||
SHARDING_INVALID_EVAL_BROADCAST: 'Script to evaluate must be a function',
|
||||
SHARDING_SHARD_NOT_FOUND: id => `Shard ${id} could not be found.`,
|
||||
SHARDING_ALREADY_SPAWNED: count => `Already spawned ${count} shards.`,
|
||||
SHARDING_PROCESS_EXISTS: id => `Shard ${id} already has an active process.`,
|
||||
|
||||
@@ -348,7 +348,7 @@ class Shard extends EventEmitter {
|
||||
// Shard is requesting an eval broadcast
|
||||
if (message._sEval) {
|
||||
const resp = { _sEval: message._sEval, _sEvalShard: message._sEvalShard };
|
||||
this.manager.broadcastEval(message._sEval, message._sEvalShard).then(
|
||||
this.manager._performOnShards('eval', [message._sEval], message._sEvalShard).then(
|
||||
results => this.send({ ...resp, _result: results }),
|
||||
err => this.send({ ...resp, _error: Util.makePlainError(err) }),
|
||||
);
|
||||
|
||||
@@ -128,29 +128,33 @@ class ShardClientUtil {
|
||||
|
||||
/**
|
||||
* Evaluates a script or function on all shards, or a given shard, in the context of the {@link Client}s.
|
||||
* @param {string|Function} script JavaScript to run on each shard
|
||||
* @param {number} [shard] Shard to run script on, all if undefined
|
||||
* @param {Function} script JavaScript to run on each shard
|
||||
* @param {BroadcastEvalOptions} [options={}] The options for the broadcast
|
||||
* @returns {Promise<*>|Promise<Array<*>>} Results of the script execution
|
||||
* @example
|
||||
* client.shard.broadcastEval('this.guilds.cache.size')
|
||||
* client.shard.broadcastEval(client => client.guilds.cache.size)
|
||||
* .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
|
||||
* .catch(console.error);
|
||||
* @see {@link ShardingManager#broadcastEval}
|
||||
*/
|
||||
broadcastEval(script, shard) {
|
||||
broadcastEval(script, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const parent = this.parentPort || process;
|
||||
script = typeof script === 'function' ? `(${script})(this)` : script;
|
||||
if (typeof script !== 'function') {
|
||||
reject(new TypeError('SHARDING_INVALID_EVAL_BROADCAST'));
|
||||
return;
|
||||
}
|
||||
script = `(${script})(this, ${JSON.stringify(options.context)})`;
|
||||
|
||||
const listener = message => {
|
||||
if (!message || message._sEval !== script || message._sEvalShard !== shard) return;
|
||||
if (!message || message._sEval !== script || message._sEvalShard !== options.shard) return;
|
||||
parent.removeListener('message', listener);
|
||||
if (!message._error) resolve(message._result);
|
||||
else reject(Util.makeError(message._error));
|
||||
};
|
||||
parent.on('message', listener);
|
||||
|
||||
this.send({ _sEval: script, _sEvalShard: shard }).catch(err => {
|
||||
this.send({ _sEval: script, _sEvalShard: options.shard }).catch(err => {
|
||||
parent.removeListener('message', listener);
|
||||
reject(err);
|
||||
});
|
||||
|
||||
@@ -226,14 +226,22 @@ class ShardingManager extends EventEmitter {
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link ShardingManager#broadcastEval} and {@link ShardClientUtil#broadcastEval}.
|
||||
* @typedef {Object} BroadcastEvalOptions
|
||||
* @property {number} [shard] Shard to run script on, all if undefined
|
||||
* @property {*} [context] The JSON-serializable values to call the script with
|
||||
*/
|
||||
|
||||
/**
|
||||
* Evaluates a script on all shards, or a given shard, in the context of the {@link Client}s.
|
||||
* @param {string} script JavaScript to run on each shard
|
||||
* @param {number} [shard] Shard to run on, all if undefined
|
||||
* @param {Function} script JavaScript to run on each shard
|
||||
* @param {BroadcastEvalOptions} [options={}] The options for the broadcast
|
||||
* @returns {Promise<*>|Promise<Array<*>>} Results of the script execution
|
||||
*/
|
||||
broadcastEval(script, shard) {
|
||||
return this._performOnShards('eval', [script], shard);
|
||||
broadcastEval(script, options = {}) {
|
||||
if (typeof script !== 'function') return Promise.reject(new TypeError('SHARDING_INVALID_EVAL_BROADCAST'));
|
||||
return this._performOnShards('eval', [`(${script})(this, ${JSON.stringify(options.context)})`], options.shard);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
15
typings/index.d.ts
vendored
15
typings/index.d.ts
vendored
@@ -1655,10 +1655,8 @@ declare module 'discord.js' {
|
||||
public readonly ids: number[];
|
||||
public mode: ShardingManagerMode;
|
||||
public parentPort: any | null;
|
||||
public broadcastEval(script: string): Promise<any[]>;
|
||||
public broadcastEval(script: string, shard: number): Promise<any>;
|
||||
public broadcastEval<T>(fn: (client: Client) => T): Promise<T[]>;
|
||||
public broadcastEval<T>(fn: (client: Client) => T, shard: number): Promise<T>;
|
||||
public broadcastEval<T, P>(fn: (client: Client, context: P) => T, { shard: undefined, context: P }?: BroadcastEvalOptions): Promise<T[]>;
|
||||
public broadcastEval<T, P>(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise<T>;
|
||||
public fetchClientValues(prop: string): Promise<any[]>;
|
||||
public fetchClientValues(prop: string, shard: number): Promise<any>;
|
||||
public respawnAll(options?: { shardDelay?: number; respawnDelay?: number; timeout?: number }): Promise<void>;
|
||||
@@ -1681,8 +1679,8 @@ declare module 'discord.js' {
|
||||
public totalShards: number | 'auto';
|
||||
public shardList: number[] | 'auto';
|
||||
public broadcast(message: any): Promise<Shard[]>;
|
||||
public broadcastEval(script: string): Promise<any[]>;
|
||||
public broadcastEval(script: string, shard: number): Promise<any>;
|
||||
public broadcastEval<T, P>(fn: (client: Client, context: P) => T, { shard: undefined, context: P }?: BroadcastEvalOptions): Promise<T[]>;
|
||||
public broadcastEval<T, P>(fn: (client: Client, context: P) => T, { shard: number, context: P }: BroadcastEvalOptions): Promise<T>;
|
||||
public createShard(id: number): Shard;
|
||||
public fetchClientValues(prop: string): Promise<any[]>;
|
||||
public fetchClientValues(prop: string, shard: number): Promise<any>;
|
||||
@@ -2536,6 +2534,11 @@ declare module 'discord.js' {
|
||||
| N
|
||||
| Readonly<BitField<T, N>>;
|
||||
|
||||
interface BroadcastEvalOptions<T = unknown> {
|
||||
shard?: number;
|
||||
context?: T;
|
||||
}
|
||||
|
||||
type BufferResolvable = Buffer | string;
|
||||
|
||||
interface ChannelCreationOverwrites {
|
||||
|
||||
Reference in New Issue
Block a user