import { createClient, RedisClientType } from 'redis'; import { redisUrl } from '@/src/lib/env-exporter' class RedisClient { private client: RedisClientType; private subscriberClient: RedisClientType | null = null; private isConnected: boolean = false; constructor() { this.client = createClient({ url: redisUrl, }); this.client.on('error', (err) => { console.error('Redis Client Error:', err); }); this.client.on('connect', () => { console.log('Redis Client Connected'); this.isConnected = true; }); this.client.on('disconnect', () => { console.log('Redis Client Disconnected'); this.isConnected = false; }); this.client.on('ready', () => { console.log('Redis Client Ready'); }); this.client.on('reconnecting', () => { console.log('Redis Client Reconnecting'); }); // Connect immediately (fire and forget) this.client.connect().catch((err) => { console.error('Failed to connect Redis:', err); }); } async set(key: string, value: string, ttlSeconds?: number): Promise { if (ttlSeconds) { return await this.client.setEx(key, ttlSeconds, value); } else { return await this.client.set(key, value); } } async get(key: string): Promise { return await this.client.get(key); } async exists(key: string): Promise { const result = await this.client.exists(key); return result === 1; } async delete(key: string): Promise { return await this.client.del(key); } async lPush(key: string, value: string): Promise { return await this.client.lPush(key, value); } async KEYS(pattern: string): Promise { return await this.client.KEYS(pattern); } async MGET(keys: string[]): Promise<(string | null)[]> { return await this.client.MGET(keys); } // Publish message to a channel async publish(channel: string, message: string): Promise { return await this.client.publish(channel, message); } // Subscribe to a channel with callback async subscribe(channel: string, callback: (message: string) => void): Promise { if (!this.subscriberClient) { this.subscriberClient = createClient({ url: redisUrl, }); this.subscriberClient.on('error', (err) => { console.error('Redis Subscriber Error:', err); }); this.subscriberClient.on('connect', () => { console.log('Redis Subscriber Connected'); }); await this.subscriberClient.connect(); } await this.subscriberClient.subscribe(channel, callback); console.log(`Subscribed to channel: ${channel}`); } // Unsubscribe from a channel async unsubscribe(channel: string): Promise { if (this.subscriberClient) { await this.subscriberClient.unsubscribe(channel); console.log(`Unsubscribed from channel: ${channel}`); } } disconnect(): void { if (this.isConnected) { this.client.disconnect(); } if (this.subscriberClient) { this.subscriberClient.disconnect(); } } get isClientConnected(): boolean { return this.isConnected; } } const redisClient = new RedisClient(); export default redisClient; export { RedisClient };