Add SKIP_REDIS environment variable and handle KeyDB client initialization in various services

This commit is contained in:
Marco Pedone 2025-08-04 18:59:33 +02:00
parent edd57928c7
commit ef58dc618c
7 changed files with 43 additions and 1 deletions

View file

@ -26,6 +26,7 @@ env:
TILES_URL: "keydb://string"
KEYDB_URL: "keydb://string"
JWT_SECRET: "335922ae"
SKIP_REDIS: "false"
jobs:
build:
runs-on: ubuntu-latest

View file

@ -62,6 +62,7 @@ ENV KEYDB_URL=$KEYDB_URL
ARG TILES_URL
ENV TILES_URL=$TILES_URL
ENV NEXT_TELEMETRY_DISABLED=1
ENV SKIP_REDIS=1
RUN SKIP_ENV_VALIDATION=1 npm run build
@ -117,6 +118,7 @@ ENV KEYDB_URL=$KEYDB_URL
ARG TILES_URL
ENV TILES_URL=$TILES_URL
ENV NEXT_TELEMETRY_DISABLED=1
ENV SKIP_REDIS=0
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

View file

@ -29,6 +29,7 @@ const server = z.object({
TILES_URL: z.string(),
KEYDB_URL: z.string(),
JWT_SECRET: z.string(),
SKIP_REDIS: z.coerce.boolean(),
});
/**
@ -70,6 +71,7 @@ const processEnv = {
TILES_URL: process.env.TILES_URL,
KEYDB_URL: process.env.KEYDB_URL,
JWT_SECRET: process.env.JWT_SECRET,
SKIP_REDIS: process.env.SKIP_REDIS,
};
// Don't touch the part below

View file

@ -88,6 +88,13 @@ export const chatSSERouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const chatKey = `chat:${input.chatId}:onlineUsers`;
const keydb = getKeydbClient();
if (!keydb) {
console.warn(
"KeyDB client is not initialized. Skipping online status.",
);
return [];
}
// Add the user to the Redis set
await keydb.sadd(
chatKey,
@ -114,6 +121,12 @@ export const chatSSERouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const chatKey = `chat:${input.chatId}:onlineUsers`;
const keydb = getKeydbClient();
if (!keydb) {
console.warn(
"KeyDB client is not initialized. Skipping online status.",
);
return [];
}
// Remove the user from the Redis set
await keydb.srem(
chatKey,

View file

@ -210,7 +210,10 @@ export const addTyping = async ({
userId,
username,
});
if (!keydb) {
console.warn("KeyDB client is not initialized. Skipping typing status.");
return;
}
// Add the user to the Redis set with a TTL
await keydb.zadd(typingKey, new Date().getTime(), typingData);
} catch (e) {
@ -233,6 +236,10 @@ export const removeTyping = async ({
try {
const keydb = getKeydbClient();
const typingKey = `${TYPING_KEY_PREFIX}${chatId}`;
if (!keydb) {
console.warn("KeyDB client is not initialized. Skipping typing removal.");
return;
}
await keydb.zrem(typingKey, JSON.stringify({ userId, username }));
} catch (e) {
@ -250,6 +257,12 @@ export const removeStaleTyping = async (chatId: ChatsChatid) => {
const typingKey = `${TYPING_KEY_PREFIX}${chatId}`;
const now = new Date();
const cutoff = subSeconds(now, TYPING_TTL_SECONDS);
if (!keydb) {
console.warn(
"KeyDB client is not initialized. Skipping stale typing removal.",
);
return;
}
await keydb.zremrangebyscore(typingKey, 0, cutoff.getTime());
} catch (e) {
@ -268,6 +281,10 @@ export const getCurrentlyTyping = async (
try {
const keydb = getKeydbClient();
const typingKey = `${TYPING_KEY_PREFIX}${chatId}`;
if (!keydb) {
console.warn("KeyDB client is not initialized. Skipping typing status.");
return [];
}
// Fetch all members of the Redis set
const allTypers = await keydb.zrange(typingKey, 0, -1);

View file

@ -23,6 +23,10 @@ export class RateLimiterHandler {
* @param key The key to limit, "event_identifier" is recommended
*/
async limit(key: string): Promise<{ success: boolean }> {
if (!keydb) {
console.warn("KeyDB client is not initialized. Skipping rate limiting.");
return { success: true };
}
const redisKey = `ratelimiter:${key}`;
const { windowSize, maxRequests, analytics } = this.config;
// Increment the count atomically

View file

@ -4,6 +4,9 @@ import { env } from "~/env.mjs";
let keydb: Redis | null = null;
export function getKeydbClient() {
if (env.SKIP_REDIS) {
return null;
}
if (!keydb) {
keydb = new Redis(`keydb://${env.KEYDB_URL}`);
}