Refactor queue management to use lazy initialization and improve Redis connection handling
- Updated queue and QueueEvents initialization to be lazy, preventing unnecessary Redis connections during the build process. - Refactored queue access methods to ensure consistent connection handling across the application. - Enhanced error handling for Redis connections during production builds to reduce log noise.
This commit is contained in:
@@ -8,6 +8,11 @@ import { redis } from './redis';
|
||||
* drawing winners, restoring a guild backup) is enqueued here and picked up
|
||||
* by the bot's existing workers - the WebUI never talks to Discord directly
|
||||
* for these actions.
|
||||
*
|
||||
* Queues and QueueEvents are created lazily on first use. Eager construction
|
||||
* at import time would open Redis connections during `next build` (where
|
||||
* Redis is intentionally unavailable), flooding the build log with
|
||||
* ECONNREFUSED errors.
|
||||
*/
|
||||
export const giveawayQueueName = 'giveaways';
|
||||
export const scheduleQueueName = 'schedules';
|
||||
@@ -24,43 +29,68 @@ const globalForQueues = globalThis as unknown as {
|
||||
__nexumiSuggestionsQueueEvents?: QueueEvents;
|
||||
};
|
||||
|
||||
export const giveawayQueue: Queue =
|
||||
globalForQueues.__nexumiGiveawayQueue ?? new Queue(giveawayQueueName, { connection: redis });
|
||||
function queueConnection() {
|
||||
return redis;
|
||||
}
|
||||
|
||||
export const scheduleQueue: Queue =
|
||||
globalForQueues.__nexumiScheduleQueue ?? new Queue(scheduleQueueName, { connection: redis });
|
||||
/** QueueEvents needs its own connection; duplicate inherits lazyConnect. */
|
||||
function queueEventsConnection() {
|
||||
return redis.duplicate();
|
||||
}
|
||||
|
||||
export const guildBackupQueue: Queue =
|
||||
globalForQueues.__nexumiGuildBackupQueue ?? new Queue(guildBackupQueueName, { connection: redis });
|
||||
export function getGiveawayQueue(): Queue {
|
||||
globalForQueues.__nexumiGiveawayQueue ??= new Queue(giveawayQueueName, {
|
||||
connection: queueConnection()
|
||||
});
|
||||
return globalForQueues.__nexumiGiveawayQueue;
|
||||
}
|
||||
|
||||
export const suggestionsQueue: Queue =
|
||||
globalForQueues.__nexumiSuggestionsQueue ?? new Queue(suggestionsQueueName, { connection: redis });
|
||||
export function getScheduleQueue(): Queue {
|
||||
globalForQueues.__nexumiScheduleQueue ??= new Queue(scheduleQueueName, {
|
||||
connection: queueConnection()
|
||||
});
|
||||
return globalForQueues.__nexumiScheduleQueue;
|
||||
}
|
||||
|
||||
export function getGuildBackupQueue(): Queue {
|
||||
globalForQueues.__nexumiGuildBackupQueue ??= new Queue(guildBackupQueueName, {
|
||||
connection: queueConnection()
|
||||
});
|
||||
return globalForQueues.__nexumiGuildBackupQueue;
|
||||
}
|
||||
|
||||
export function getSuggestionsQueue(): Queue {
|
||||
globalForQueues.__nexumiSuggestionsQueue ??= new Queue(suggestionsQueueName, {
|
||||
connection: queueConnection()
|
||||
});
|
||||
return globalForQueues.__nexumiSuggestionsQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* QueueEvents instances are only needed for jobs where the dashboard needs
|
||||
* to wait for the bot to finish (e.g. ending a giveaway so the winners list
|
||||
* is immediately visible). They open their own Redis connection, so they are
|
||||
* cached on the global object the same way as the queues themselves.
|
||||
* is immediately visible).
|
||||
*/
|
||||
export const giveawayQueueEvents: QueueEvents =
|
||||
globalForQueues.__nexumiGiveawayQueueEvents ??
|
||||
new QueueEvents(giveawayQueueName, { connection: redis.duplicate() });
|
||||
export function getGiveawayQueueEvents(): QueueEvents {
|
||||
globalForQueues.__nexumiGiveawayQueueEvents ??= new QueueEvents(giveawayQueueName, {
|
||||
connection: queueEventsConnection()
|
||||
});
|
||||
return globalForQueues.__nexumiGiveawayQueueEvents;
|
||||
}
|
||||
|
||||
export const guildBackupQueueEvents: QueueEvents =
|
||||
globalForQueues.__nexumiGuildBackupQueueEvents ??
|
||||
new QueueEvents(guildBackupQueueName, { connection: redis.duplicate() });
|
||||
export function getGuildBackupQueueEvents(): QueueEvents {
|
||||
globalForQueues.__nexumiGuildBackupQueueEvents ??= new QueueEvents(guildBackupQueueName, {
|
||||
connection: queueEventsConnection()
|
||||
});
|
||||
return globalForQueues.__nexumiGuildBackupQueueEvents;
|
||||
}
|
||||
|
||||
export const suggestionsQueueEvents: QueueEvents =
|
||||
globalForQueues.__nexumiSuggestionsQueueEvents ??
|
||||
new QueueEvents(suggestionsQueueName, { connection: redis.duplicate() });
|
||||
|
||||
globalForQueues.__nexumiGiveawayQueue = giveawayQueue;
|
||||
globalForQueues.__nexumiScheduleQueue = scheduleQueue;
|
||||
globalForQueues.__nexumiGuildBackupQueue = guildBackupQueue;
|
||||
globalForQueues.__nexumiSuggestionsQueue = suggestionsQueue;
|
||||
globalForQueues.__nexumiGiveawayQueueEvents = giveawayQueueEvents;
|
||||
globalForQueues.__nexumiGuildBackupQueueEvents = guildBackupQueueEvents;
|
||||
globalForQueues.__nexumiSuggestionsQueueEvents = suggestionsQueueEvents;
|
||||
export function getSuggestionsQueueEvents(): QueueEvents {
|
||||
globalForQueues.__nexumiSuggestionsQueueEvents ??= new QueueEvents(suggestionsQueueName, {
|
||||
connection: queueEventsConnection()
|
||||
});
|
||||
return globalForQueues.__nexumiSuggestionsQueueEvents;
|
||||
}
|
||||
|
||||
const DEFAULT_WAIT_TIMEOUT_MS = 15_000;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user