fix: cache flow

This commit is contained in:
MARCROCK22 2024-06-01 20:14:40 +00:00
parent bf3db57c71
commit 0da67319f3
4 changed files with 1315 additions and 1359 deletions

View File

@ -22,7 +22,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
memberUpdateHandler = new MemberUpdateHandler(); memberUpdateHandler = new MemberUpdateHandler();
presenceUpdateHandler = new PresenceUpdateHandler(); presenceUpdateHandler = new PresenceUpdateHandler();
collectors = new Collectors(); collectors = new Collectors();
events? = new EventHandler(this.logger, this.collectors); events? = new EventHandler(this);
constructor(options?: ClientOptions) { constructor(options?: ClientOptions) {
super(options); super(options);
@ -51,7 +51,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
if (!rest.handlers.events) { if (!rest.handlers.events) {
this.events = undefined; this.events = undefined;
} else if (typeof rest.handlers.events === 'function') { } else if (typeof rest.handlers.events === 'function') {
this.events = new EventHandler(this.logger, this.collectors); this.events = new EventHandler(this);
this.events.setHandlers({ this.events.setHandlers({
callback: rest.handlers.events, callback: rest.handlers.events,
}); });
@ -132,7 +132,7 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
} }
protected async onPacket(shardId: number, packet: GatewayDispatchPayload) { protected async onPacket(shardId: number, packet: GatewayDispatchPayload) {
await this.events?.runEvent('RAW', this, packet, shardId); // await this.events?.runEvent('RAW', this, packet, shardId);
switch (packet.t) { switch (packet.t) {
//// Cases where we must obtain the old data before updating //// Cases where we must obtain the old data before updating
case 'GUILD_MEMBER_UPDATE': case 'GUILD_MEMBER_UPDATE':
@ -140,36 +140,16 @@ export class Client<Ready extends boolean = boolean> extends BaseClient {
return; return;
} }
await this.events?.execute(packet.t, packet, this as Client<true>, shardId); await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
await this.cache.onPacket(packet);
break; break;
case 'PRESENCE_UPDATE': case 'PRESENCE_UPDATE':
if (!this.presenceUpdateHandler.check(packet.d as any)) { if (!this.presenceUpdateHandler.check(packet.d as any)) {
return; return;
} }
await this.events?.execute(packet.t, packet, this as Client<true>, shardId); await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
await this.cache.onPacket(packet);
break; break;
case 'MESSAGE_UPDATE':
case 'MESSAGE_DELETE_BULK':
case 'MESSAGE_DELETE':
case 'GUILD_DELETE':
case 'CHANNEL_UPDATE':
case 'GUILD_EMOJIS_UPDATE':
case 'GUILD_UPDATE':
case 'GUILD_ROLE_UPDATE':
case 'GUILD_ROLE_DELETE':
case 'THREAD_UPDATE':
case 'USER_UPDATE':
case 'VOICE_STATE_UPDATE':
case 'STAGE_INSTANCE_UPDATE':
case 'GUILD_STICKERS_UPDATE':
await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
await this.cache.onPacket(packet);
break;
//rest of the events //rest of the events
default: { default: {
await this.cache.onPacket(packet);
await this.events?.execute(packet.t, packet, this as Client<true>, shardId); await this.events?.execute(packet.t, packet, this as Client<true>, shardId);
switch (packet.t) { switch (packet.t) {
case 'INTERACTION_CREATE': case 'INTERACTION_CREATE':

View File

@ -48,7 +48,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
}); });
collectors = new Collectors(); collectors = new Collectors();
events? = new EventHandler(this.logger, this.collectors); events? = new EventHandler(this);
me!: When<Ready, ClientUser>; me!: When<Ready, ClientUser>;
promises = new Map<string, { resolve: (value: any) => void; timeout: NodeJS.Timeout }>(); promises = new Map<string, { resolve: (value: any) => void; timeout: NodeJS.Timeout }>();
@ -119,7 +119,7 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
if (!rest.handlers.events) { if (!rest.handlers.events) {
this.events = undefined; this.events = undefined;
} else if (typeof rest.handlers.events === 'function') { } else if (typeof rest.handlers.events === 'function') {
this.events = new EventHandler(this.logger, this.collectors); this.events = new EventHandler(this);
this.events.setHandlers({ this.events.setHandlers({
callback: rest.handlers.events, callback: rest.handlers.events,
}); });
@ -204,7 +204,6 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
debugger: this.debugger, debugger: this.debugger,
async handlePayload(shardId, payload) { async handlePayload(shardId, payload) {
await handlePayload?.(shardId, payload); await handlePayload?.(shardId, payload);
await self.cache.onPacket(payload);
await onPacket?.(payload, shardId); await onPacket?.(payload, shardId);
self.postMessage({ self.postMessage({
workerId: workerData.workerId, workerId: workerData.workerId,
@ -325,79 +324,49 @@ export class WorkerClient<Ready extends boolean = boolean> extends BaseClient {
protected async onPacket(packet: GatewayDispatchPayload, shardId: number) { protected async onPacket(packet: GatewayDispatchPayload, shardId: number) {
await this.events?.execute('RAW', packet, this as WorkerClient<true>, shardId); await this.events?.execute('RAW', packet, this as WorkerClient<true>, shardId);
await this.events?.execute(packet.t, packet, this, shardId);
switch (packet.t) { switch (packet.t) {
case 'GUILD_MEMBER_UPDATE': case 'READY':
case 'PRESENCE_UPDATE': for (const g of packet.d.guilds) {
this.__handleGuilds?.add(g.id);
case 'MESSAGE_UPDATE':
case 'MESSAGE_DELETE_BULK':
case 'MESSAGE_DELETE':
case 'GUILD_DELETE':
case 'CHANNEL_UPDATE':
case 'GUILD_EMOJIS_UPDATE':
case 'GUILD_UPDATE':
case 'GUILD_ROLE_UPDATE':
case 'GUILD_ROLE_DELETE':
case 'THREAD_UPDATE':
case 'USER_UPDATE':
case 'VOICE_STATE_UPDATE':
case 'STAGE_INSTANCE_UPDATE':
case 'GUILD_STICKERS_UPDATE':
await this.events?.execute(packet.t, packet, this as WorkerClient<true>, shardId);
await this.cache.onPacket(packet);
break;
//rest of the events
default:
{
await this.events?.execute(packet.t, packet, this, shardId);
switch (packet.t) {
case 'READY':
for (const g of packet.d.guilds) {
this.__handleGuilds?.add(g.id);
}
this.botId = packet.d.user.id;
this.applicationId = packet.d.application.id;
this.me = new ClientUser(this, packet.d.user, packet.d.application) as never;
if (
!(
this.__handleGuilds?.size &&
(workerData.intents & GatewayIntentBits.Guilds) === GatewayIntentBits.Guilds
)
) {
if ([...this.shards.values()].every(shard => shard.data.session_id)) {
this.postMessage({
type: 'WORKER_READY',
workerId: this.workerId,
} as WorkerReady);
await this.events?.runEvent('WORKER_READY', this, this.me, -1);
}
delete this.__handleGuilds;
}
this.debugger?.debug(`#${shardId} [${packet.d.user.username}](${this.botId}) is online...`);
break;
case 'INTERACTION_CREATE':
await onInteractionCreate(this, packet.d, shardId);
break;
case 'MESSAGE_CREATE':
await onMessageCreate(this, packet.d, shardId);
break;
case 'GUILD_CREATE': {
if (this.__handleGuilds?.has(packet.d.id)) {
this.__handleGuilds.delete(packet.d.id);
if (!this.__handleGuilds.size && [...this.shards.values()].every(shard => shard.data.session_id)) {
this.postMessage({
type: 'WORKER_READY',
workerId: this.workerId,
} as WorkerReady);
await this.events?.runEvent('WORKER_READY', this, this.me, -1);
}
if (!this.__handleGuilds.size) delete this.__handleGuilds;
return;
}
}
}
} }
this.botId = packet.d.user.id;
this.applicationId = packet.d.application.id;
this.me = new ClientUser(this, packet.d.user, packet.d.application) as never;
if (
!(this.__handleGuilds?.size && (workerData.intents & GatewayIntentBits.Guilds) === GatewayIntentBits.Guilds)
) {
if ([...this.shards.values()].every(shard => shard.data.session_id)) {
this.postMessage({
type: 'WORKER_READY',
workerId: this.workerId,
} as WorkerReady);
await this.events?.runEvent('WORKER_READY', this, this.me, -1);
}
delete this.__handleGuilds;
}
this.debugger?.debug(`#${shardId} [${packet.d.user.username}](${this.botId}) is online...`);
break; break;
case 'INTERACTION_CREATE':
await onInteractionCreate(this, packet.d, shardId);
break;
case 'MESSAGE_CREATE':
await onMessageCreate(this, packet.d, shardId);
break;
case 'GUILD_CREATE': {
if (this.__handleGuilds?.has(packet.d.id)) {
this.__handleGuilds.delete(packet.d.id);
if (!this.__handleGuilds.size && [...this.shards.values()].every(shard => shard.data.session_id)) {
this.postMessage({
type: 'WORKER_READY',
workerId: this.workerId,
} as WorkerReady);
await this.events?.runEvent('WORKER_READY', this, this.me, -1);
}
if (!this.__handleGuilds.size) delete this.__handleGuilds;
return;
}
}
} }
} }
} }

View File

@ -5,22 +5,18 @@ import type {
GatewayMessageDeleteDispatch, GatewayMessageDeleteDispatch,
} from 'discord-api-types/v10'; } from 'discord-api-types/v10';
import type { Client, WorkerClient } from '../client'; import type { Client, WorkerClient } from '../client';
import { BaseHandler, type Logger, ReplaceRegex, magicImport, type MakeRequired, type SnakeCase } from '../common'; import { BaseHandler, ReplaceRegex, magicImport, type MakeRequired, type SnakeCase } from '../common';
import type { ClientEvents } from '../events/hooks'; import type { ClientEvents } from '../events/hooks';
import * as RawEvents from '../events/hooks'; import * as RawEvents from '../events/hooks';
import type { ClientEvent, ClientNameEvents } from './event'; import type { ClientEvent, ClientNameEvents } from './event';
import type { Collectors } from '../client/collectors';
export type EventValue = MakeRequired<ClientEvent, '__filePath'> & { fired?: boolean }; export type EventValue = MakeRequired<ClientEvent, '__filePath'> & { fired?: boolean };
export type GatewayEvents = Uppercase<SnakeCase<keyof ClientEvents>>; export type GatewayEvents = Uppercase<SnakeCase<keyof ClientEvents>>;
export class EventHandler extends BaseHandler { export class EventHandler extends BaseHandler {
constructor( constructor(protected client: Client | WorkerClient) {
logger: Logger, super(client.logger);
protected collectors: Collectors,
) {
super(logger);
} }
onFail = (event: GatewayEvents, err: unknown) => this.logger.warn('<Client>.events.onFail', err, event); onFail = (event: GatewayEvents, err: unknown) => this.logger.warn('<Client>.events.onFail', err, event);
@ -78,20 +74,31 @@ export class EventHandler extends BaseHandler {
} }
await this.runEvent(args[0].t, args[1], args[0].d, args[2]); await this.runEvent(args[0].t, args[1], args[0].d, args[2]);
await this.collectors.run(args[0].t, args[0].d); await this.client.collectors.run(args[0].t, args[0].d);
} }
async runEvent(name: GatewayEvents, client: Client | WorkerClient, packet: any, shardId: number) { async runEvent(name: GatewayEvents, client: Client | WorkerClient, packet: any, shardId: number) {
const Event = this.values[name]; const Event = this.values[name];
if (!Event) { if (!Event) {
return; return this.client.cache.onPacket({
t: name,
d: packet,
} as GatewayDispatchPayload);
} }
try { try {
if (Event.data.once && Event.fired) { if (Event.data.once && Event.fired) {
return; return this.client.cache.onPacket({
t: name,
d: packet,
} as GatewayDispatchPayload);
} }
Event.fired = true; Event.fired = true;
const hook = await RawEvents[name]?.(client, packet as never); const hook = await RawEvents[name]?.(client, packet as never);
if (name !== 'RAW')
await this.client.cache.onPacket({
t: name,
d: packet,
} as GatewayDispatchPayload);
await Event.run(...[hook, client, shardId]); await Event.run(...[hook, client, shardId]);
} catch (e) { } catch (e) {
await this.onFail(name, e); await this.onFail(name, e);