diff --git a/apps/infoalloggi/.github/workflows/ci.yml b/apps/infoalloggi/.github/workflows/ci.yml index 7a26d2a..0e002ab 100644 --- a/apps/infoalloggi/.github/workflows/ci.yml +++ b/apps/infoalloggi/.github/workflows/ci.yml @@ -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 diff --git a/apps/infoalloggi/Dockerfile b/apps/infoalloggi/Dockerfile index 720f841..6a82b6e 100644 --- a/apps/infoalloggi/Dockerfile +++ b/apps/infoalloggi/Dockerfile @@ -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 diff --git a/apps/infoalloggi/src/env.mjs b/apps/infoalloggi/src/env.mjs index b8bc355..a46cff9 100644 --- a/apps/infoalloggi/src/env.mjs +++ b/apps/infoalloggi/src/env.mjs @@ -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 diff --git a/apps/infoalloggi/src/server/api/routers/chat_sse.ts b/apps/infoalloggi/src/server/api/routers/chat_sse.ts index 5f383d2..167c672 100644 --- a/apps/infoalloggi/src/server/api/routers/chat_sse.ts +++ b/apps/infoalloggi/src/server/api/routers/chat_sse.ts @@ -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, diff --git a/apps/infoalloggi/src/server/controllers/chat.controller.ts b/apps/infoalloggi/src/server/controllers/chat.controller.ts index 3e8316e..e31f0d2 100644 --- a/apps/infoalloggi/src/server/controllers/chat.controller.ts +++ b/apps/infoalloggi/src/server/controllers/chat.controller.ts @@ -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); diff --git a/apps/infoalloggi/src/server/services/ratelimiter.ts b/apps/infoalloggi/src/server/services/ratelimiter.ts index dcbc6e4..3a21b8f 100644 --- a/apps/infoalloggi/src/server/services/ratelimiter.ts +++ b/apps/infoalloggi/src/server/services/ratelimiter.ts @@ -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 diff --git a/apps/infoalloggi/src/utils/keydb.ts b/apps/infoalloggi/src/utils/keydb.ts index e47c1e7..8ce66ee 100644 --- a/apps/infoalloggi/src/utils/keydb.ts +++ b/apps/infoalloggi/src/utils/keydb.ts @@ -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}`); }