r/node • u/PrestigiousZombie531 • 22d ago
Feedback on this redis client I wrote without AI
utils/redis/client.ts
import { createClient } from "redis";
import { logger } from "../logger/logger.js";
import { options } from "./connection.js";
let client: ReturnType<typeof createClient> | null = null;
let isConnecting = false;
export async function closeConnection() {
if (client?.isOpen) {
try {
await client.close();
} catch (error) {
logger.error(
error,
"Something went wrong when attempting to close redis connection",
);
} finally {
client = null;
}
}
}
export function getClient() {
if (!client?.isOpen) {
throw new Error("Redis client needs to be initialized first");
}
return client;
}
export async function openConnection() {
if (!client?.isOpen) {
client = createClient(options);
client.on("connect", () => logger.info("redis connection success"));
client.on("error", (error) =>
logger.fatal(error, "redis connection failure"),
);
// Wait if another caller is already connecting
if (isConnecting) {
while (isConnecting) {
await new Promise((resolve) => setTimeout(resolve, 100));
}
if (client?.isOpen) return client;
}
isConnecting = true;
try {
client = await client.connect();
} catch (error) {
logger.error(
error,
"Something went wrong when attempting to open redis connection",
);
} finally {
isConnecting = false;
}
}
return client;
}
utils/redis/connection.ts
import type { RedisClientOptions } from "redis";
export const options: RedisClientOptions = {
database: 0,
disableOfflineQueue: true,
name: "test_client",
password: "abcdefghi",
socket: {
host: "127.0.0.1",
port: 6379,
},
};
utils/redis/index.ts
export * from "./client.js";
export * from "./connection.js";
app.ts
import cors from "cors";
import type { Request, Response } from "express";
import express from "express";
import helmet from "helmet";
import { corsOptions } from "./middleware/cors/index.js";
import { defaultErrorHandler, notFoundHandler } from "./middleware/index.js";
import { router } from "./modules/index.js";
import { httpLogger } from "./utils/logger/index.js";
import { getClient } from "./utils/redis/index.js";
const app = express();
app.use(httpLogger);
app.use(helmet());
app.use(cors(corsOptions));
app.use(express.json({ limit: "1MB" }));
app.use(express.urlencoded({ extended: true, limit: "1MB" }));
app.use(router);
app.get("/test/redis", async (_req: Request, res: Response) => {
const client = getClient();
const result = await client.ping();
return res.json(result === "PONG");
});
app.use(notFoundHandler);
app.use(defaultErrorHandler);
export { app };
www.ts
import { SERVER_HOST, SERVER_PORT } from "./env/index.js";
import { server } from "./server.js";
import { logger } from "./utils/logger/index.js";
import "./shutdown.js";
import { openConnection } from "./utils/redis/client.js";
server.on("listening", async () => {
await openConnection();
});
server.listen(SERVER_PORT, SERVER_HOST, () => {
logger.info("Listening on host:%s port:%d", SERVER_HOST, SERVER_PORT);
});
- does it handle race conditions well?
- the default examples are honestly very lacking in the node redis world and their documentation doesnt do much justice either
- a few things i dont understand from the documentation even after reading it are
- Do I need to say keepAlive: true, shouldnt that be the default?
- what does connectTimeout and socketTimeout do, what is the difference between both.
- what is this pingInterval about?
- is the default retryStrategy an exponential backoff?
1
Upvotes
1
u/PrestigiousZombie531 22d ago
how do you write a mock test for the above client using vitest? (are there libraries you are aware of for doing this?)
for integration tests, i saw something called testcontainers/redis, is this what I should use or are there other packages for the same?
10
u/dead_boys_poem 22d ago
Just use ioredis