Skip to content

Commit

Permalink
feat: introduce new logic for handling redis errors (#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
fruneen committed Dec 13, 2023
1 parent ff18a75 commit 4a65e8e
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 19 deletions.
7 changes: 4 additions & 3 deletions template/apps/api/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ const schema = z.object({
APP_ENV: z.enum(['development', 'staging', 'production']).default('development'),
IS_DEV: z.preprocess(() => process.env.APP_ENV === 'development', z.boolean()),
PORT: z.coerce.number().optional().default(3001),
MONGO_URI: z.string(),
MONGO_DB_NAME: z.string(),
REDIS_URI: z.string(),
API_URL: z.string(),
WEB_URL: z.string(),
MONGO_URI: z.string(),
MONGO_DB_NAME: z.string(),
REDIS_URI: z.string().optional(),
REDIS_ERRORS_POLICY: z.enum(['throw', 'log']).default('log'),
SENDGRID_API_KEY: z.string().optional(),
ADMIN_KEY: z.string().optional(),
MIXPANEL_API_KEY: z.string().optional(),
Expand Down
24 changes: 13 additions & 11 deletions template/apps/api/src/io-emitter.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import { createClient } from 'redis';
import { Emitter } from '@socket.io/redis-emitter';

import config from 'config';
import redisClient from 'redis-client';
import logger from 'logger';

let emitter: Emitter | null = null;
const redisClient = createClient({ url: config.REDIS_URI });
import config from './config';

redisClient.on('error', err => {
logger.error(`ioEmitter() => Redis error: ${err.stack || err}`);
throw err;
});
let emitter: Emitter | null = null;

const publish = (roomId: string | string[], eventName: string, data: unknown) => {
if (emitter === null) {
throw new Error('ioEmitter is not initialized.');
if (config.REDIS_ERRORS_POLICY === 'throw') {
throw new Error('ioEmitter is not initialized.');
} else {
logger.debug('ioEmitter is not initialized.');
return;
}
}

logger.debug(`published io event [${eventName}] to ${roomId}, the data is: ${JSON.stringify(data)}`);

emitter.to(roomId).emit(eventName, data);
};

const initClient = async () => {
await redisClient.connect();
const subClient = redisClient.duplicate();
await subClient.connect();

emitter = new Emitter(redisClient);
emitter = new Emitter(subClient);
};

const getUserRoomId = (userId: string) => `user-${userId}`;
Expand Down
23 changes: 20 additions & 3 deletions template/apps/api/src/redis-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,28 @@ import { createClient } from 'redis';
import config from 'config';
import logger from 'logger';

const client = createClient({ url: config.REDIS_URI });
const client = createClient({
url: config.REDIS_URI,
pingInterval: 1_000,
socket: {
connectTimeout: 30_000,
reconnectStrategy: (retries) => {
const maxDelay = 5_000;
const baseDelay = 50;

return Math.min(baseDelay * Math.pow(2, retries), maxDelay);
},
},
});

client.on('error', err => {
logger.error(`redisClient => Redis error: ${err.stack || err}`);
throw err;
const errorMessage = `redisClient => Redis error: ${err.stack || err}`;

if (config.REDIS_ERRORS_POLICY === 'throw') {
throw Error(errorMessage);
} else {
logger.error(errorMessage);
}
});

export default client;
4 changes: 2 additions & 2 deletions template/apps/api/src/services/socket/socket.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import http from 'http';
import { Server } from 'socket.io';
import { createAdapter } from '@socket.io/redis-adapter';
import pubClient from 'redis-client';

import { COOKIES } from 'app-constants';

import { tokenService } from 'resources/token';

import pubClient from 'redis-client';
import logger from 'logger';

import socketHelper from './socket.helper';
Expand All @@ -17,7 +17,7 @@ export default async (server: http.Server) => {
const subClient = pubClient.duplicate();

await Promise.all([pubClient.connect(), subClient.connect()]);
logger.info('Socket.io server has been connected');
logger.info('Socket.io server has been connected.');

io.adapter(createAdapter(pubClient, subClient));

Expand Down

0 comments on commit 4a65e8e

Please sign in to comment.