From b2f65c2accfcbbca413fe3b5885f53088afbfffc Mon Sep 17 00:00:00 2001 From: Skillz Date: Sun, 20 Aug 2023 11:50:19 -0500 Subject: [PATCH] fix: chunk resolve bug --- packages/gateway/src/Shard.ts | 63 +++++++++++++++++++++++---------- packages/gateway/src/manager.ts | 14 ++++++-- 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/packages/gateway/src/Shard.ts b/packages/gateway/src/Shard.ts index aebf7107c..660f6d056 100644 --- a/packages/gateway/src/Shard.ts +++ b/packages/gateway/src/Shard.ts @@ -4,6 +4,7 @@ import type { BigString, Camelize, DiscordGatewayPayload, + DiscordGuildMembersChunk, DiscordHello, DiscordMember, DiscordReady, @@ -443,33 +444,57 @@ export class DiscordenoShard { } } - if (packet.t === 'RESUMED') { - // gateway.debug("GW RESUMED", { shardId }); + switch (packet.t) { + case 'RESUMED': + this.state = ShardState.Connected + this.events.resumed?.(this) - this.state = ShardState.Connected - this.events.resumed?.(this) + // Continue the requests which have been queued since the shard went offline. + this.offlineSendQueue.map((resolve) => resolve()) - // Continue the requests which have been queued since the shard went offline. - this.offlineSendQueue.map((resolve) => resolve()) + this.resolves.get('RESUMED')?.(packet) + this.resolves.delete('RESUMED') + break + case 'READY': { + // Important for future resumes. + const payload = packet.d as DiscordReady - this.resolves.get('RESUMED')?.(packet) - this.resolves.delete('RESUMED') - } else if (packet.t === 'READY') { - // Important for future resumes. + this.resumeGatewayUrl = payload.resume_gateway_url - const payload = packet.d as DiscordReady + this.sessionId = payload.session_id + this.state = ShardState.Connected - this.resumeGatewayUrl = payload.resume_gateway_url + // Continue the requests which have been queued since the shard went offline. + // Important when this is a re-identify + this.offlineSendQueue.map((resolve) => resolve()) - this.sessionId = payload.session_id - this.state = ShardState.Connected + this.resolves.get('READY')?.(packet) + this.resolves.delete('READY') + break + } + case 'GUILD_MEMBERS_CHUNK': { + // If it's not enabled skip checks. + if (!this.cache.requestMembers.enabled) break - // Continue the requests which have been queued since the shard went offline. - // Important when this is a re-identify - this.offlineSendQueue.map((resolve) => resolve()) + const payload = packet.d as DiscordGuildMembersChunk + // If this request has non nonce, skip checks. + if (!payload.nonce) break - this.resolves.get('READY')?.(packet) - this.resolves.delete('READY') + const pending = this.cache.requestMembers.pending.get(payload.nonce) + if (!pending) break + + // If this is not the final chunk, just save to cache. + if (payload.chunk_index + 1 < payload.chunk_count) { + pending.members.push(...payload.members) + break; + } + + // Resolve the promise that all requests are done. + pending.resolve(camelize(pending.members)) + // Delete the cache to clean up once its done. + this.cache.requestMembers.pending.delete(payload.nonce) + break + } } // Update the sequence number if it is present diff --git a/packages/gateway/src/manager.ts b/packages/gateway/src/manager.ts index 81d5db3cc..e4817b8b5 100644 --- a/packages/gateway/src/manager.ts +++ b/packages/gateway/src/manager.ts @@ -1,5 +1,13 @@ /* eslint-disable @typescript-eslint/no-confusing-void-expression */ -import type { AtLeastOne, BigString, Camelize, DiscordGetGatewayBot, DiscordMember, RequestGuildMembers } from '@discordeno/types' +import type { + AtLeastOne, + BigString, + Camelize, + DiscordGetGatewayBot, + DiscordMember, + DiscordMemberWithUser, + RequestGuildMembers, +} from '@discordeno/types' import { Collection, delay, logger } from '@discordeno/utils' import Shard from './Shard.js' import type { ShardEvents, StatusUpdate, UpdateVoiceState } from './types.js' @@ -30,7 +38,7 @@ export function createGatewayManager(options: CreateGatewayManagerOptions): Gate version: options.version ?? 10, connection: connectionOptions, totalShards: options.totalShards ?? connectionOptions.shards ?? 1, - lastShardId: options.lastShardId ?? (options.totalShards ? options.totalShards - 1 : (connectionOptions ? connectionOptions.shards - 1 : 0)), + lastShardId: options.lastShardId ?? (options.totalShards ? options.totalShards - 1 : connectionOptions ? connectionOptions.shards - 1 : 0), firstShardId: options.firstShardId ?? 0, totalWorkers: options.totalWorkers ?? 4, shardsPerWorker: options.shardsPerWorker ?? 25, @@ -480,5 +488,5 @@ export interface RequestMemberRequest { /** The resolver handler to run when all members arrive. */ resolve: (value: Camelize | PromiseLike>) => void /** The members that have already arrived for this request. */ - members: Camelize + members: DiscordMemberWithUser[] }