This commit is contained in:
Skillz
2023-01-03 13:23:54 -06:00
parent c1fc768fc1
commit 0413787680
2 changed files with 43 additions and 59 deletions

View File

@@ -2,7 +2,6 @@ import type { DiscordGatewayPayload, DiscordHello, DiscordReady } from '@discord
import { GatewayCloseEventCodes, GatewayOpcodes } from '@discordeno/types'
import { createLeakyBucket, delay } from '@discordeno/utils'
import { inflateSync } from 'zlib'
import type { GatewayManager } from './manager.js'
import type { BotStatusUpdate, ShardEvents, ShardGatewayConfig, ShardHeart, ShardSocketRequest } from './types.js'
import { ShardSocketCloseCodes, ShardState } from './types.js'
@@ -13,8 +12,8 @@ export const DEFAULT_HEARTBEAT_INTERVAL = 45000
export class Shard {
/** The id of the shard */
id: number
/** The gateway manager that is responsible for this this. */
manager: GatewayManager
/** The connection config details that this shard will used to connect to discord. */
connection: ShardGatewayConfig
/** This contains all the heartbeat information */
heart: ShardHeart
/** The maximum of requests which can be send to discord per rate limit tick. Typically this value should not be changed. */
@@ -29,12 +28,14 @@ export class Shard {
socket?: WebSocket
/** Current internal state of the this. */
state = ShardState.Offline
/** The total amount of shards which are used to communicate with Discord. */
// totalShards: number
/** The url provided by discord to use when resuming a connection for this this. */
resumeGatewayUrl: string = ''
/** The shard related event handlers. */
events: ShardEvents = {}
/** Cache for pending gateway requests which should have been send while the gateway went offline. */
offlineSendQueue: Array<(_?: unknown) => void> = []
/** Resolve internal waiting states. Mapped by SelectedEvents => ResolveFunction */
resolves = new Map<'READY' | 'RESUMED' | 'INVALID_SESSION', (payload: DiscordGatewayPayload) => void>()
/** Shard bucket. Only access this if you know what you are doing. Bucket for handling shard request rate limits. */
bucket = createLeakyBucket({
max: 120,
@@ -42,16 +43,9 @@ export class Shard {
refillAmount: 120
})
/** Cache for pending gateway requests which should have been send while the gateway went offline. */
offlineSendQueue: Array<(_?: unknown) => void> = []
/** Resolve internal waiting states. Mapped by SelectedEvents => ResolveFunction */
resolves = new Map<'READY' | 'RESUMED' | 'INVALID_SESSION', (payload: DiscordGatewayPayload) => void>()
constructor (manager: GatewayManager, shardId: number) {
constructor (shardId: number, connection: ShardGatewayConfig) {
this.id = shardId
// TODO: can this be done without a manager?
this.manager = manager
this.connection = connection
this.heart = {
acknowledged: false,
@@ -61,18 +55,7 @@ export class Shard {
/** The gateway configuration which is used to connect to Discord. */
get gatewayConfig (): ShardGatewayConfig {
return {
compress: this.manager.compress,
intents: this.manager.intents,
properties: {
os: this.manager.properties.os,
browser: this.manager.properties.browser,
device: this.manager.properties.device
},
token: this.manager.token,
url: this.manager.url,
version: this.manager.version
}
return this.connection
}
/** Calculate the amount of requests which can safely be made per rate limit interval, before the gateway gets disconnected due to an exceeded rate limit. */
@@ -174,7 +157,7 @@ export class Shard {
compress: this.gatewayConfig.compress,
properties: this.gatewayConfig.properties,
intents: this.gatewayConfig.intents,
shard: [this.id, this.manager.totalShards],
shard: [this.id, this.gatewayConfig.totalShards],
presence: await this.makePresence?.()
}
},

View File

@@ -4,15 +4,11 @@ import type Shard from './Shard.js'
export enum ShardState {
/** Shard is fully connected to the gateway and receiving events from Discord. */
Connected = 0,
/** Shard started to connect to the gateway.
* This is only used if the shard is not currently trying to identify or resume.
*/
/** Shard started to connect to the gateway. This is only used if the shard is not currently trying to identify or resume. */
Connecting = 1,
/** Shard got disconnected and reconnection actions have been started. */
Disconnected = 2,
/** The shard is connected to the gateway but only heartbeating.
* At this state the shard has not been identified with discord.
*/
/** The shard is connected to the gateway but only heartbeating. At this state the shard has not been identified with discord. */
Unidentified = 3,
/** Shard is trying to identify with the gateway to create a new session. */
Identifying = 4,
@@ -24,45 +20,50 @@ export enum ShardState {
export interface ShardGatewayConfig {
/** Whether incoming payloads are compressed using zlib.
*
* @default false
*/
*
* @default false
*/
compress: boolean
/** The calculated intent value of the events which the shard should receive.
*
* @default 0
*/
*
* @default 0
*/
intents: number
/** Identify properties to use */
properties: {
/** Operating system the shard runs on.
*
* @default "darwin" | "linux" | "windows"
*/
*
* @default "darwin" | "linux" | "windows"
*/
os: string
/** The "browser" where this shard is running on.
*
* @default "Discordeno"
*/
*
* @default "Discordeno"
*/
browser: string
/** The device on which the shard is running.
*
* @default "Discordeno"
*/
*
* @default "Discordeno"
*/
device: string
}
/** Bot token which is used to connect to Discord */
token: string
/** The URL of the gateway which should be connected to.
*
* @default "wss://gateway.discord.gg"
*/
*
* @default "wss://gateway.discord.gg"
*/
url: string
/** The gateway version which should be used.
*
* @default 10
*/
*
* @default 10
*/
version: number
/**
* The total number of shards to connect to across the entire bot.
* @default 1
*/
totalShards: number
}
export interface ShardHeart {
@@ -77,9 +78,9 @@ export interface ShardHeart {
/** Unix timestamp (in milliseconds) when the last heartbeat was sent. */
lastBeat?: number
/** Round trip time (in milliseconds) from Shard to Discord and back.
* Calculated using the heartbeat system.
* Note: this value is undefined until the first heartbeat to Discord has happened.
*/
* Calculated using the heartbeat system.
* Note: this value is undefined until the first heartbeat to Discord has happened.
*/
rtt?: number
/** Id of the timeout which is used for sending the first heartbeat to Discord since it's "special". */
timeoutId?: NodeJS.Timeout
@@ -120,8 +121,8 @@ export enum ShardSocketCloseCodes {
/** A resume has been requested and therefore the old connection needs to be closed. */
ResumeClosingOldConnection = 3024,
/** Did not receive a heartbeat ACK in time.
* Closing the shard and creating a new session.
*/
* Closing the shard and creating a new session.
*/
ZombiedConnection = 3010,
/** Discordeno's gateway tests hae been finished, therefore the Shard can be turned off. */
TestingFinished = 3064,