mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-14 02:23:31 +01:00
fix: Internal Sharding, this time fixed™ (#3140)
* src: WIP Internal Sharding refactor * src: Refactor unavailable guild check Co-Authored-By: kyranet <kyradiscord@gmail.com> * src: More WIP Code F in the chat to the old manager * src: It should work but Discord says no. Seriously why is this not working! * fix: Inflator causing issues * src: Finishing touches and typings * misc: Proper debug message * fix: Making things hidden needs writable: true as well * fix: Sharding allowing multiple of the same shard, negative shards or strings * fix: Again... edge cases I love you guys .w. * misc: Touchups * misc: Better error? * docs: Typo * typings: Requested changes * src: Requested changes * src: Fix issues, validate provided shard options and more * src: Forgot to remove the listener * lint: eslint complaining * fix: Setting shardCount to auto crashing the process * misc: Requested changes * typings: Correct typings for shardCount client option * typings: Add invalidSession event to the shard and correct typings * src: Minor docs adjustements, and code consistency between setHelloTimeout and setHeartbeatTimeout * src: Don't block reconnect while creating shards Might fix silent disconnects *again* * src: Prevent reconnect from running if the Manager isn't READY That way, if a shard dies while we're still spawning, it won't cause issues * fix: Retry to reconnect if there's a network error going on. The manager *should* keep reconnecting unless the token is invalid * src: Enhance onClose handler for shards in the manager - If the close code is between 1000 and 2000 (inclusive), you cannot resume I tested this locally - If there's a session ID still present, immediately try to resume Faster resumes :papaBless: Otherwise, the invalid session event will trigger and it'll handle accordingly I swear if I see a SINGULAR Silent DC I'm yeeting * src: Fix error check * src: Make sure message exists on the error * src: Used the wrong property for the shardQueue * src: Make the hello timeout be made by the client god help * docs: Correct docs for WSEvents * misc: Remove old events from the Events constant * src: Throw the HTTP error if we don't get a 401 * typings: Can't forget about them * src: Implement some more fail safes just in case Seriously, better safe than sorry! Gotta failproof it completely
This commit is contained in:
97
typings/index.d.ts
vendored
97
typings/index.d.ts
vendored
@@ -2,6 +2,7 @@ declare module 'discord.js' {
|
||||
import { EventEmitter } from 'events';
|
||||
import { Stream, Readable, Writable } from 'stream';
|
||||
import { ChildProcess } from 'child_process';
|
||||
import * as WebSocket from 'ws';
|
||||
|
||||
export const version: string;
|
||||
|
||||
@@ -181,15 +182,18 @@ declare module 'discord.js' {
|
||||
public on(event: 'presenceUpdate', listener: (oldPresence: Presence | undefined, newPresence: Presence) => void): this;
|
||||
public on(event: 'rateLimit', listener: (rateLimitData: RateLimitData) => void): this;
|
||||
public on(event: 'ready', listener: () => void): this;
|
||||
public on(event: 'reconnecting', listener: (shardID: number) => void): this;
|
||||
public on(event: 'resumed', listener: (replayed: number, shardID: number) => void): this;
|
||||
public on(event: 'roleCreate' | 'roleDelete', listener: (role: Role) => void): this;
|
||||
public on(event: 'roleUpdate', listener: (oldRole: Role, newRole: Role) => void): this;
|
||||
public on(event: 'shardReady', listener: (shardID: number) => void): this;
|
||||
public on(event: 'typingStart' | 'typingStop', listener: (channel: Channel, user: User) => void): this;
|
||||
public on(event: 'userUpdate', listener: (oldUser: User, newUser: User) => void): this;
|
||||
public on(event: 'voiceStateUpdate', listener: (oldState: VoiceState | undefined, newState: VoiceState) => void): this;
|
||||
public on(event: 'webhookUpdate', listener: (channel: TextChannel) => void): this;
|
||||
public on(event: 'invalidated', listener: () => void): this;
|
||||
public on(event: 'shardDisconnected', listener: (event: CloseEvent, id: number) => void): this;
|
||||
public on(event: 'shardError', listener: (error: Error, id: number) => void): this;
|
||||
public on(event: 'shardReconnecting', listener: (id: number) => void): this;
|
||||
public on(event: 'shardReady', listener: (id: number) => void): this;
|
||||
public on(event: 'shardResumed', listener: (id: number) => void): this;
|
||||
public on(event: string, listener: Function): this;
|
||||
|
||||
public once(event: 'channelCreate' | 'channelDelete', listener: (channel: Channel) => void): this;
|
||||
@@ -215,15 +219,18 @@ declare module 'discord.js' {
|
||||
public once(event: 'presenceUpdate', listener: (oldPresence: Presence | undefined, newPresence: Presence) => void): this;
|
||||
public once(event: 'rateLimit', listener: (rateLimitData: RateLimitData) => void): this;
|
||||
public once(event: 'ready', listener: () => void): this;
|
||||
public once(event: 'reconnecting', listener: (shardID: number) => void): this;
|
||||
public once(event: 'resumed', listener: (replayed: number, shardID: number) => void): this;
|
||||
public once(event: 'roleCreate' | 'roleDelete', listener: (role: Role) => void): this;
|
||||
public once(event: 'roleUpdate', listener: (oldRole: Role, newRole: Role) => void): this;
|
||||
public once(event: 'shardReady', listener: (shardID: number) => void): this;
|
||||
public once(event: 'typingStart' | 'typingStop', listener: (channel: Channel, user: User) => void): this;
|
||||
public once(event: 'userUpdate', listener: (oldUser: User, newUser: User) => void): this;
|
||||
public once(event: 'voiceStateUpdate', listener: (oldState: VoiceState | undefined, newState: VoiceState) => void): this;
|
||||
public once(event: 'webhookUpdate', listener: (channel: TextChannel) => void): this;
|
||||
public once(event: 'invalidated', listener: () => void): this;
|
||||
public once(event: 'shardDisconnected', listener: (event: CloseEvent, id: number) => void): this;
|
||||
public once(event: 'shardError', listener: (error: Error, id: number) => void): this;
|
||||
public once(event: 'shardReconnecting', listener: (id: number) => void): this;
|
||||
public once(event: 'shardReady', listener: (id: number) => void): this;
|
||||
public once(event: 'shardResumed', listener: (id: number) => void): this;
|
||||
public once(event: string, listener: Function): this;
|
||||
}
|
||||
|
||||
@@ -340,12 +347,13 @@ declare module 'discord.js' {
|
||||
}
|
||||
|
||||
export class DiscordAPIError extends Error {
|
||||
constructor(path: string, error: object, method: string);
|
||||
constructor(path: string, error: object, method: string, httpStatus: number);
|
||||
private static flattenErrors(obj: object, key: string): string[];
|
||||
|
||||
public code: number;
|
||||
public method: string;
|
||||
public path: string;
|
||||
public httpStatus: number;
|
||||
}
|
||||
|
||||
export class DMChannel extends TextBasedChannel(Channel) {
|
||||
@@ -1270,27 +1278,80 @@ declare module 'discord.js' {
|
||||
|
||||
export class WebSocketManager {
|
||||
constructor(client: Client);
|
||||
private totalShards: number | string;
|
||||
private shardQueue: Set<WebSocketShard>;
|
||||
private packetQueue: object[];
|
||||
private destroyed: boolean;
|
||||
private reconnecting: boolean;
|
||||
private sessionStartLimit?: { total: number; remaining: number; reset_after: number; };
|
||||
|
||||
public readonly client: Client;
|
||||
public gateway: string | undefined;
|
||||
public readonly ping: number;
|
||||
public gateway?: string;
|
||||
public shards: Collection<number, WebSocketShard>;
|
||||
public status: Status;
|
||||
public readonly ping: number;
|
||||
|
||||
public broadcast(packet: object): void;
|
||||
private debug(message: string, shard?: WebSocketShard): void;
|
||||
private connect(): Promise<void>;
|
||||
private createShards(): Promise<void>;
|
||||
private reconnect(): Promise<void>;
|
||||
private broadcast(packet: object): void;
|
||||
private destroy(): void;
|
||||
private _handleSessionLimit(remaining?: number, resetAfter?: number): Promise<void>;
|
||||
private handlePacket(packet?: object, shard?: WebSocketShard): Promise<boolean>;
|
||||
private checkReady(): boolean;
|
||||
private triggerReady(): void;
|
||||
}
|
||||
|
||||
export class WebSocketShard extends EventEmitter {
|
||||
constructor(manager: WebSocketManager, id: number);
|
||||
public id: number;
|
||||
public readonly ping: number;
|
||||
public pings: number[];
|
||||
public status: Status;
|
||||
private sequence: number;
|
||||
private closeSequence: number;
|
||||
private sessionID?: string;
|
||||
private lastPingTimestamp: number;
|
||||
private lastHeartbeatAcked: boolean;
|
||||
private trace: string[];
|
||||
private ratelimit: { queue: object[]; total: number; remaining: number; time: 60e3; timer: NodeJS.Timeout | null; };
|
||||
private connection: WebSocket | null;
|
||||
private helloTimeout: NodeJS.Timeout | null;
|
||||
private eventsAttached: boolean;
|
||||
|
||||
public manager: WebSocketManager;
|
||||
public id: number;
|
||||
public status: Status;
|
||||
public pings: [number, number, number];
|
||||
public readonly ping: number;
|
||||
|
||||
public send(packet: object): void;
|
||||
private debug(message: string): void;
|
||||
private connect(): Promise<void>;
|
||||
private onOpen(): void;
|
||||
private onMessage(event: MessageEvent): void;
|
||||
private onError(error: ErrorEvent): void;
|
||||
private onClose(event: CloseEvent): void;
|
||||
private onPacket(packet: object): void;
|
||||
private setHelloTimeout(time?: number): void;
|
||||
private setHeartbeatTimer(time: number): void;
|
||||
private sendHeartbeat(): void;
|
||||
private ackHeartbeat(): void;
|
||||
private identify(): void;
|
||||
private identifyNew(): void;
|
||||
private identifyResume(): void;
|
||||
private _send(data: object): void;
|
||||
private processQueue(): void;
|
||||
private destroy(closeCode: number): void;
|
||||
|
||||
public send(data: object): void;
|
||||
public on(event: 'ready', listener: () => void): this;
|
||||
public on(event: 'resumed', listener: () => void): this;
|
||||
public on(event: 'close', listener: (event: CloseEvent) => void): this;
|
||||
public on(event: 'invalidSession', listener: () => void): this;
|
||||
public on(event: string, listener: Function): this;
|
||||
|
||||
public once(event: 'ready', listener: () => void): this;
|
||||
public once(event: 'resumed', listener: () => void): this;
|
||||
public once(event: 'close', listener: (event: CloseEvent) => void): this;
|
||||
public once(event: 'invalidSession', listener: () => void): this;
|
||||
public once(event: string, listener: Function): this;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -1589,7 +1650,7 @@ declare module 'discord.js' {
|
||||
|
||||
interface ClientOptions {
|
||||
shards?: number | number[];
|
||||
shardCount?: number;
|
||||
shardCount?: number | 'auto';
|
||||
totalShardCount?: number;
|
||||
messageCacheMaxSize?: number;
|
||||
messageCacheLifetime?: number;
|
||||
@@ -2149,5 +2210,9 @@ declare module 'discord.js' {
|
||||
| 'VOICE_SERVER_UPDATE'
|
||||
| 'WEBHOOKS_UPDATE';
|
||||
|
||||
type MessageEvent = { data: WebSocket.Data; type: string; target: WebSocket; };
|
||||
type CloseEvent = { wasClean: boolean; code: number; reason: string; target: WebSocket; };
|
||||
type ErrorEvent = { error: any, message: string, type: string, target: WebSocket; };
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user