change: implement new better unavailable check

This commit is contained in:
ITOH
2021-05-13 10:49:23 +02:00
parent 23b0e1d383
commit 9b8fe4e336
2 changed files with 43 additions and 51 deletions
+1 -1
View File
@@ -24,8 +24,8 @@ export async function handleGuildCreate(
if (shard?.unavailableGuildIds.has(guild.id)) { if (shard?.unavailableGuildIds.has(guild.id)) {
await cacheHandlers.delete("unavailableGuilds", guild.id); await cacheHandlers.delete("unavailableGuilds", guild.id);
shard.unavailableGuildIds.delete(guild.id); shard.unavailableGuildIds.delete(guild.id);
shard.lastAvailable = Date.now();
return eventHandlers.guildAvailable?.(guild); return eventHandlers.guildAvailable?.(guild);
} }
+27 -35
View File
@@ -3,7 +3,7 @@ import { cache } from "../../cache.ts";
import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts";
import type { Ready } from "../../types/gateway/ready.ts"; import type { Ready } from "../../types/gateway/ready.ts";
import { snowflakeToBigint } from "../../util/bigint.ts"; import { snowflakeToBigint } from "../../util/bigint.ts";
import { ws } from "../../ws/ws.ts"; import { DiscordenoShard, ws } from "../../ws/ws.ts";
export function handleReady( export function handleReady(
data: DiscordGatewayPayload, data: DiscordGatewayPayload,
@@ -12,17 +12,15 @@ export function handleReady(
// The bot has already started, the last shard is resumed, however. // The bot has already started, the last shard is resumed, however.
if (cache.isReady) return; if (cache.isReady) return;
const shard = ws.shards.get(shardId);
if (!shard) return;
const payload = data.d as Ready; const payload = data.d as Ready;
setBotId(payload.user.id); setBotId(payload.user.id);
setApplicationId(payload.application.id); setApplicationId(payload.application.id);
// Triggered on each shard // Triggered on each shard
eventHandlers.shardReady?.(shardId); eventHandlers.shardReady?.(shard);
// Save when the READY event was received to prevent infinite load loops
const now = Date.now();
const shard = ws.shards.get(shardId);
if (!shard) return;
// Set ready to false just to go sure // Set ready to false just to go sure
shard.ready = false; shard.ready = false;
@@ -30,6 +28,8 @@ export function handleReady(
shard.unavailableGuildIds = new Set( shard.unavailableGuildIds = new Set(
payload.guilds.map((g) => snowflakeToBigint(g.id)), payload.guilds.map((g) => snowflakeToBigint(g.id)),
); );
// Set the last available to now
shard.lastAvailable = Date.now();
// Start ready check in 2 seconds // Start ready check in 2 seconds
setTimeout(() => { setTimeout(() => {
@@ -37,46 +37,38 @@ export function handleReady(
"loop", "loop",
`1. Running setTimeout in READY file.`, `1. Running setTimeout in READY file.`,
); );
checkReady(payload, shardId, now); checkReady(payload, shard);
}, 2000); }, 2000);
} }
// Don't pass the shard itself because unavailableGuilds won't be updated by the GUILD_CREATE event
/** This function checks if the shard is fully loaded */ /** This function checks if the shard is fully loaded */
function checkReady(payload: Ready, shardId: number, now: number) { function checkReady(payload: Ready, shard: DiscordenoShard) {
const shard = ws.shards.get(shardId);
if (!shard) return;
// Check if all guilds were loaded // Check if all guilds were loaded
if (shard.unavailableGuildIds.size) { if (!shard.unavailableGuildIds.size) return loaded(shard);
if (Date.now() - now > 10000) {
eventHandlers.shardFailedToLoad?.(shardId, shard.unavailableGuildIds); // If the last GUILD_CREATE has been received before 5 seconds if so most likely the remaining guilds are unavailable
if (shard.lastAvailable + 5000 < Date.now()) {
eventHandlers.shardFailedToLoad?.(shard, shard.unavailableGuildIds);
// Force execute the loaded function to prevent infinite loop // Force execute the loaded function to prevent infinite loop
loaded(shardId); loaded(shard);
} else { }
// Not all guilds were loaded but 10 seconds haven't passed so check again
// Not all guilds were loaded but 5 seconds haven't passed so check again
setTimeout(() => { setTimeout(() => {
eventHandlers.debug?.( eventHandlers.debug?.(
"loop", "loop",
`2. Running setTimeout in READY file.`, `2. Running setTimeout in READY file.`,
); );
checkReady(payload, shardId, now); checkReady(payload, shard);
}, 2000); }, 2000);
} }
} else {
// All guilds were loaded
loaded(shardId);
}
}
function loaded(shardId: number) {
const shard = ws.shards.get(shardId);
if (!shard) return;
function loaded(shard: DiscordenoShard) {
shard.ready = true; shard.ready = true;
// If it is the last shard we can go full ready // If it is not the last shard we can't go full ready
if (shardId === ws.maxShards - 1) { if (shard.id !== ws.maxShards - 1) return;
// Still some shards are loading so wait another 2 seconds for them // Still some shards are loading so wait another 2 seconds for them
if (ws.shards.some((shard) => !shard.ready)) { if (ws.shards.some((shard) => !shard.ready)) {
setTimeout(() => { setTimeout(() => {
@@ -84,11 +76,11 @@ function loaded(shardId: number) {
"loop", "loop",
`3. Running setTimeout in READY file.`, `3. Running setTimeout in READY file.`,
); );
loaded(shardId); loaded(shard);
}, 2000); }, 2000);
} else { return;
}
cache.isReady = true; cache.isReady = true;
eventHandlers.ready?.(); eventHandlers.ready?.();
} }
}
}