Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Sharding): Change waitForReady to spawnTimeout #3080

Merged
merged 2 commits into from Apr 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 11 additions & 9 deletions src/sharding/Shard.js
Expand Up @@ -102,10 +102,11 @@ class Shard extends EventEmitter {
/**
* Forks a child process or creates a worker thread for the shard.
* <warn>You should not need to call this manually.</warn>
* @param {boolean} [waitForReady=true] Whether to wait until the {@link Client} has become ready before resolving
* @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready
* before resolving. (-1 or Infinity for no wait)
* @returns {Promise<ChildProcess>}
*/
async spawn(waitForReady = true) {
async spawn(spawnTimeout = 30000) {
if (this.process) throw new Error('SHARDING_PROCESS_EXISTS', this.id);
if (this.worker) throw new Error('SHARDING_WORKER_EXISTS', this.id);

Expand All @@ -128,12 +129,12 @@ class Shard extends EventEmitter {
*/
this.emit('spawn', this.process || this.worker);

if (!waitForReady) return this.process || this.worker;
if (spawnTimeout === -1 || spawnTimeout === Infinity) return this.process || this.worker;
await new Promise((resolve, reject) => {
this.once('ready', resolve);
this.once('disconnect', () => reject(new Error('SHARDING_READY_DISCONNECTED', this.id)));
this.once('death', () => reject(new Error('SHARDING_READY_DIED', this.id)));
setTimeout(() => reject(new Error('SHARDING_READY_TIMEOUT', this.id)), 30000);
setTimeout(() => reject(new Error('SHARDING_READY_TIMEOUT', this.id)), spawnTimeout);
});
return this.process || this.worker;
}
Expand All @@ -156,13 +157,14 @@ class Shard extends EventEmitter {
/**
* Kills and restarts the shard's process/worker.
* @param {number} [delay=500] How long to wait between killing the process/worker and restarting it (in milliseconds)
* @param {boolean} [waitForReady=true] Whether to wait until the {@link Client} has become ready before resolving
* @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready
* before resolving. (-1 or Infinity for no wait)
* @returns {Promise<ChildProcess>}
*/
async respawn(delay = 500, waitForReady = true) {
async respawn(delay = 500, spawnTimeout) {
this.kill();
if (delay > 0) await Util.delayFor(delay);
return this.spawn(waitForReady);
return this.spawn(spawnTimeout);
}

/**
Expand Down Expand Up @@ -308,8 +310,8 @@ class Shard extends EventEmitter {

// Shard is requesting a respawn of all shards
if (message._sRespawnAll) {
const { shardDelay, respawnDelay, waitForReady } = message._sRespawnAll;
this.manager.respawnAll(shardDelay, respawnDelay, waitForReady).catch(() => {
const { shardDelay, respawnDelay, spawnTimeout } = message._sRespawnAll;
this.manager.respawnAll(shardDelay, respawnDelay, spawnTimeout).catch(() => {
// Do nothing
});
return;
Expand Down
7 changes: 4 additions & 3 deletions src/sharding/ShardClientUtil.js
Expand Up @@ -143,12 +143,13 @@ class ShardClientUtil {
* @param {number} [shardDelay=5000] How long to wait between shards (in milliseconds)
* @param {number} [respawnDelay=500] How long to wait between killing a shard's process/worker and restarting it
* (in milliseconds)
* @param {boolean} [waitForReady=true] Whether to wait for a shard to become ready before continuing to another
* @param {number} [spawnTimeout=30000] The amount in milliseconds to wait for a shard to become ready before
* continuing to another. (-1 or Infinity for no wait)
* @returns {Promise<void>} Resolves upon the message being sent
* @see {@link ShardingManager#respawnAll}
*/
respawnAll(shardDelay = 5000, respawnDelay = 500, waitForReady = true) {
return this.send({ _sRespawnAll: { shardDelay, respawnDelay, waitForReady } });
respawnAll(shardDelay = 5000, respawnDelay = 500, spawnTimeout = 30000) {
return this.send({ _sRespawnAll: { shardDelay, respawnDelay, spawnTimeout } });
}

/**
Expand Down
16 changes: 9 additions & 7 deletions src/sharding/ShardingManager.js
Expand Up @@ -156,12 +156,13 @@ class ShardingManager extends EventEmitter {

/**
* Spawns multiple shards.
* @param {number} [amount=this.totalShards] Number of shards to spawn
* @param {number|string} [amount=this.totalShards] Number of shards to spawn
* @param {number} [delay=5500] How long to wait in between spawning each shard (in milliseconds)
* @param {boolean} [waitForReady=true] Whether to wait for a shard to become ready before continuing to another
* @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready
* before resolving. (-1 or Infinity for no wait)
* @returns {Promise<Collection<number, Shard>>}
*/
async spawn(amount = this.totalShards, delay = 5500, waitForReady = true) {
async spawn(amount = this.totalShards, delay = 5500, spawnTimeout) {
// Obtain/verify the number of shards to spawn
if (amount === 'auto') {
amount = await Util.fetchRecommendedShards(this.token);
Expand Down Expand Up @@ -193,7 +194,7 @@ class ShardingManager extends EventEmitter {
for (const shardID of this.shardList) {
const promises = [];
const shard = this.createShard(shardID);
promises.push(shard.spawn(waitForReady));
promises.push(shard.spawn(spawnTimeout));
if (delay > 0 && this.shards.size !== this.shardList.length) promises.push(Util.delayFor(delay));
await Promise.all(promises); // eslint-disable-line no-await-in-loop
}
Expand Down Expand Up @@ -245,13 +246,14 @@ class ShardingManager extends EventEmitter {
* @param {number} [shardDelay=5000] How long to wait between shards (in milliseconds)
* @param {number} [respawnDelay=500] How long to wait between killing a shard's process and restarting it
* (in milliseconds)
* @param {boolean} [waitForReady=true] Whether to wait for a shard to become ready before continuing to another
* @param {number} [spawnTimeout=30000] The amount in milliseconds to wait for a shard to become ready before
* continuing to another. (-1 or Infinity for no wait)
* @returns {Promise<Collection<string, Shard>>}
*/
async respawnAll(shardDelay = 5000, respawnDelay = 500, waitForReady = true) {
async respawnAll(shardDelay = 5000, respawnDelay = 500, spawnTimeout) {
let s = 0;
for (const shard of this.shards.values()) {
const promises = [shard.respawn(respawnDelay, waitForReady)];
const promises = [shard.respawn(respawnDelay, spawnTimeout)];
if (++s < this.shards.size && shardDelay > 0) promises.push(Util.delayFor(shardDelay));
await Promise.all(promises); // eslint-disable-line no-await-in-loop
}
Expand Down
10 changes: 5 additions & 5 deletions typings/index.d.ts
Expand Up @@ -921,9 +921,9 @@ declare module 'discord.js' {
public eval<T>(fn: (client: Client) => T): Promise<T[]>;
public fetchClientValue(prop: string): Promise<any>;
public kill(): void;
public respawn(delay?: number, waitForReady?: boolean): Promise<ChildProcess>;
public respawn(delay?: number, spawnTimeout?: number): Promise<ChildProcess>;
public send(message: any): Promise<Shard>;
public spawn(waitForReady?: boolean): Promise<ChildProcess>;
public spawn(spawnTimeout?: number): Promise<ChildProcess>;

public on(event: 'death', listener: (child: ChildProcess) => void): this;
public on(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => void): this;
Expand Down Expand Up @@ -953,7 +953,7 @@ declare module 'discord.js' {
public broadcastEval(script: string): Promise<any[]>;
public broadcastEval<T>(fn: (client: Client) => T): Promise<T[]>;
public fetchClientValues(prop: string): Promise<any[]>;
public respawnAll(shardDelay?: number, respawnDelay?: number, waitForReady?: boolean): Promise<void>;
public respawnAll(shardDelay?: number, respawnDelay?: number, spawnTimeout?: number): Promise<void>;
public send(message: any): Promise<void>;

public static singleton(client: Client, mode: ShardingManagerMode): ShardClientUtil;
Expand All @@ -979,8 +979,8 @@ declare module 'discord.js' {
public broadcastEval(script: string): Promise<any[]>;
public createShard(id: number): Shard;
public fetchClientValues(prop: string): Promise<any[]>;
public respawnAll(shardDelay?: number, respawnDelay?: number, waitForReady?: boolean): Promise<Collection<number, Shard>>;
public spawn(amount?: number | 'auto', delay?: number, waitForReady?: boolean): Promise<Collection<number, Shard>>;
public respawnAll(shardDelay?: number, respawnDelay?: number, spawnTimeout?: number): Promise<Collection<number, Shard>>;
public spawn(amount?: number | 'auto', delay?: number, spawnTimeout?: number): Promise<Collection<number, Shard>>;

public on(event: 'shardCreate', listener: (shard: Shard) => void): this;

Expand Down