Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/events/ready.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import BaseEventListener from '#main/core/BaseEventListener.js';
import Scheduler from '#main/modules/SchedulerService.js';
import updateBlacklists from '#main/tasks/updateBlacklists.js';
import cacheClient from '#main/utils/cache/cacheClient.js';
import Logger from '#main/utils/Logger.js';
import Logger from '#utils/Logger.js';
import getRedis from '#utils/Redis.js';
import { Client } from 'discord.js';

export default class Ready extends BaseEventListener<'ready'> {
readonly name = 'ready';
public async execute(client: Client<true>) {
Logger.info(`Logged in as ${client.user.tag}!`);

const redisClient = getRedis();
const shardId = client.guilds.cache.first()?.shardId;
const blacklistScheduled = (await cacheClient.get('blacklistScheduled')) ?? shardId?.toString();
const blacklistScheduled = (await redisClient.get('blacklistScheduled')) ?? shardId?.toString();

if (shardId === 0 && blacklistScheduled === '0') {
updateBlacklists(client);
Expand All @@ -23,7 +24,7 @@ export default class Ready extends BaseEventListener<'ready'> {
updateBlacklists(client),
);

cacheClient.set('blacklistScheduled', `${shardId}`);
redisClient.set('blacklistScheduled', `${shardId}`);
}
}
}
13 changes: 8 additions & 5 deletions src/modules/CooldownService.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import cacheClient from '#main/utils/cache/cacheClient.js';
import getRedis from '#utils/Redis.js';
import { RedisKeys } from '#main/config/Constants.js';

/** Manage and store individual cooldowns */
export default class CooldownService {
private redisClient = getRedis();
private readonly prefix = RedisKeys.cooldown;

private getKey(id: string) {
return `${RedisKeys.cooldown}:${id}`;
return `${this.prefix}:${id}`;
}
/**
* Set a cooldown
* @param id A unique id for the cooldown
* @param ms The duration of the cooldown in milliseconds
*/
public async setCooldown(id: string, ms: number) {
await cacheClient.set(this.getKey(id), Date.now() + ms, 'PX', ms);
await this.redisClient.set(this.getKey(id), Date.now() + ms, 'PX', ms);
}

/** Get a cooldown */
public async getCooldown(id: string) {
return parseInt((await cacheClient.get(this.getKey(id))) || '0');
return parseInt((await this.redisClient.get(this.getKey(id))) || '0');
}

/** Delete a cooldown */
public async deleteCooldown(id: string) {
await cacheClient.del(this.getKey(id));
await this.redisClient.del(this.getKey(id));
}

/** Get the remaining cooldown in milliseconds */
Expand Down
12 changes: 6 additions & 6 deletions src/utils/ConnectedListUtils.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { RedisKeys } from '#main/config/Constants.js';
import Logger from '#main/utils/Logger.js';
import cacheClient from '#main/utils/cache/cacheClient.js';
import Logger from '#utils/Logger.js';
import getRedis from '#utils/Redis.js';
import type { connectedList, Prisma } from '@prisma/client';
import db from '#main/utils/Db.js';
import { cacheData, getCachedData } from '#main/utils/cache/cacheUtils.js';
import db from '#utils/Db.js';
import { cacheData, getCachedData } from '#utils/cache/cacheUtils.js';

type whereUniuqeInput = Prisma.connectedListWhereUniqueInput;
type whereInput = Prisma.connectedListWhereInput;
type dataInput = Prisma.connectedListUpdateInput;
type ConnectionOperation = 'create' | 'modify' | 'delete';

const purgeConnectionCache = async (channelId: string) =>
await cacheClient.del(`${RedisKeys.connectionHubId}:${channelId}`);
await getRedis().del(`${RedisKeys.connectionHubId}:${channelId}`);

const serializeConnection = (connection: ConvertDatesToString<connectedList>) => ({
...connection,
Expand Down Expand Up @@ -79,7 +79,7 @@ export const syncHubConnCache = async (

const cacheConnectionHubId = async (connection: connectedList) => {
if (!connection.connected) {
await cacheClient.del(`${RedisKeys.connectionHubId}:${connection.channelId}`);
await getRedis().del(`${RedisKeys.connectionHubId}:${connection.channelId}`);
}
else {
await cacheData(
Expand Down
11 changes: 11 additions & 0 deletions src/utils/Redis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Redis } from 'ioredis';

// when run usin scripts like registerCmds
let redisClient: Redis;

export const getRedis = () => {
if (!redisClient) redisClient = new Redis(process.env.REDIS_URI as string);
return redisClient;
};

export default getRedis;
8 changes: 0 additions & 8 deletions src/utils/cache/cacheClient.ts

This file was deleted.

39 changes: 7 additions & 32 deletions src/utils/cache/cacheUtils.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { RedisKeys } from '#main/config/Constants.js';
import cacheClient from '#main/utils/cache/cacheClient.js';
import Logger from '#main/utils/Logger.js';
import getRedis from '#utils/Redis.js';
import Logger from '#utils/Logger.js';
import { Prisma } from '@prisma/client';
import { type Awaitable } from 'discord.js';

// TODO: make this into a class

export const cacheData = async (key: string, value: string, expirySecs?: number) => {
try {
return await cacheClient.set(key, value, 'EX', expirySecs ?? 5 * 60);
await getRedis().set(key, value, 'EX', expirySecs ?? 5 * 60);
}
catch (e) {
Logger.error('Failed to set cache: ', e);
Expand All @@ -21,10 +21,11 @@ export const parseKey = (key: string) => {
};

export const invalidateCacheForModel = async (model: string) => {
const allCacheKeys = await cacheClient.keys('*');
const redisClient = getRedis();
const allCacheKeys = await redisClient.keys('*');
allCacheKeys.forEach(async (key) => {
if (parseKey(key).model === model) {
await cacheClient.del(`${model}:${key}`);
await redisClient.del(`${model}:${key}`);
}
});
};
Expand All @@ -40,32 +41,6 @@ export const serializeCache = <K>(data: string | null): ConvertDatesToString<K>
}
};

export const traverseCursor = async (
result: [cursor: string, elements: string[]],
match: string,
start: number,
): Promise<[cursor: string, elements: string[]]> => {
const cursor = parseInt(result[0]);
if (isNaN(cursor) || cursor === 0) return result;

const newRes = await cacheClient.scan(start, 'MATCH', match, 'COUNT', 100);

result[0] = newRes[0];
result[1].push(...newRes[1]);

if (newRes[0] !== '0') return await traverseCursor(result, match, start);
return result;
};

export const getAllDocuments = async (match: string) => {
const firstIter = await cacheClient.scan(0, 'MATCH', match, 'COUNT', 100);
const keys = (await traverseCursor(firstIter, match, 100))[1];
const result = (await Promise.all(keys.map(async (key) => await cacheClient.get(key)))).filter(
Boolean,
) as string[];
return result;
};

const isCacheable = (data: unknown): boolean =>
Array.isArray(data) ? data.length > 0 : data !== null && data !== undefined;

Expand All @@ -76,7 +51,7 @@ export const getCachedData = async <
fetchFunction?: (() => Awaitable<T | null>) | null,
expiry?: number,
) => {
let data = serializeCache<T>(await cacheClient.get(key));
let data = serializeCache<T>(await getRedis().get(key));
const fromCache = isCacheable(data);

if (!fromCache && fetchFunction) {
Expand Down
10 changes: 5 additions & 5 deletions src/utils/moderation/deleteMessage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { RedisKeys } from '#main/config/Constants.js';
import cacheClient from '#main/utils/cache/cacheClient.js';
import { cacheData, getCachedData } from '#main/utils/cache/cacheUtils.js';
import { getHubConnections } from '#main/utils/ConnectedListUtils.js';
import getRedis from '#utils/Redis.js';
import { cacheData, getCachedData } from '#utils/cache/cacheUtils.js';
import { getHubConnections } from '#utils/ConnectedListUtils.js';
import { broadcastedMessages } from '@prisma/client';
import { Snowflake, WebhookClient } from 'discord.js';

Expand Down Expand Up @@ -32,11 +32,11 @@ export const deleteMessageFromHub = async (
deletedCount++;
}

await cacheClient.del(`${RedisKeys.msgDeleteInProgress}:${originalMsgId}`);
await getRedis().del(`${RedisKeys.msgDeleteInProgress}:${originalMsgId}`);
return { deletedCount };
};

export const isDeleteInProgress = async (originalMsgId: Snowflake) => {
const res = await cacheClient.get(`${RedisKeys.msgDeleteInProgress}:${originalMsgId}`);
const res = await getRedis().get(`${RedisKeys.msgDeleteInProgress}:${originalMsgId}`);
return res === 't';
};
12 changes: 6 additions & 6 deletions src/utils/network/storeMessageData.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { updateConnections } from '#main/utils/ConnectedListUtils.js';
import { updateConnections } from '#utils/ConnectedListUtils.js';
import { ConnectionMode, RedisKeys } from '#main/config/Constants.js';
import db from '#main/utils/Db.js';
import Logger from '#main/utils/Logger.js';
import cacheClient from '#main/utils/cache/cacheClient.js';
import db from '#utils/Db.js';
import Logger from '#utils/Logger.js';
import getRedis from '#utils/Redis.js';
import { originalMessages } from '@prisma/client';
import { APIMessage, Message } from 'discord.js';
import { getCachedData } from '#main/utils/cache/cacheUtils.js';
import { getCachedData } from '#utils/cache/cacheUtils.js';

interface ErrorResult {
webhookURL: string;
Expand All @@ -30,7 +30,7 @@ const storeMessageTimestamp = async (message: Message) => {
{ channelId: message.channelId, timestamp: message.createdTimestamp },
]);

await cacheClient.set(`${RedisKeys.msgTimestamp}:all`, data);
await getRedis().set(`${RedisKeys.msgTimestamp}:all`, data);
};

/**
Expand Down