"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisService = void 0; const redis_1 = require("redis"); const Logger_1 = require("./Logger"); class RedisService { constructor() { this.isConnected = false; const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379'; this.client = (0, redis_1.createClient)({ url: redisUrl, socket: { reconnectStrategy: (retries) => Math.min(retries * 50, 500) } }); this.client.on('error', (err) => { (0, Logger_1.logError)('Redis connection error', err); this.isConnected = false; }); this.client.on('connect', () => { (0, Logger_1.logStartup)('Redis client connected successfully'); this.isConnected = true; }); this.client.on('disconnect', () => { (0, Logger_1.logWarning)('Redis client disconnected'); this.isConnected = false; }); } static getInstance() { if (!RedisService.instance) { RedisService.instance = new RedisService(); } return RedisService.instance; } async connect() { try { if (!this.isConnected) { await this.client.connect(); } } catch (error) { (0, Logger_1.logError)('Failed to connect to Redis', error); throw error; } } async disconnect() { try { if (this.isConnected) { await this.client.disconnect(); } } catch (error) { (0, Logger_1.logError)('Failed to disconnect from Redis', error); } } async setActiveChat(chatId, chatData) { try { const key = `active_chat:${chatId}`; await this.client.hSet(key, { chatId: chatData.chatId, participants: JSON.stringify(chatData.participants), lastActivity: chatData.lastActivity.toISOString(), messageCount: chatData.messageCount.toString(), chatType: chatData.chatType, gameId: chatData.gameId || '', name: chatData.name || '' }); // Set expiration for 1 hour of inactivity await this.client.expire(key, 3600); } catch (error) { (0, Logger_1.logError)(`Failed to set active chat ${chatId}`, error); } } async getActiveChat(chatId) { try { const key = `active_chat:${chatId}`; const data = await this.client.hGetAll(key); if (!data.chatId) { return null; } return { chatId: data.chatId, participants: JSON.parse(data.participants), lastActivity: new Date(data.lastActivity), messageCount: parseInt(data.messageCount, 10), chatType: data.chatType, gameId: data.gameId || undefined, name: data.name || undefined }; } catch (error) { (0, Logger_1.logError)(`Failed to get active chat ${chatId}`, error); return null; } } async removeActiveChat(chatId) { try { const key = `active_chat:${chatId}`; await this.client.del(key); } catch (error) { (0, Logger_1.logError)(`Failed to remove active chat ${chatId}`, error); } } async getAllActiveChats() { try { const pattern = 'active_chat:*'; const keys = await this.client.keys(pattern); const chats = []; for (const key of keys) { const data = await this.client.hGetAll(key); if (data.chatId) { chats.push({ chatId: data.chatId, participants: JSON.parse(data.participants), lastActivity: new Date(data.lastActivity), messageCount: parseInt(data.messageCount, 10), chatType: data.chatType, gameId: data.gameId || undefined, name: data.name || undefined }); } } return chats; } catch (error) { (0, Logger_1.logError)('Failed to get all active chats', error); return []; } } async setActiveUser(userId, userData) { try { const key = `active_user:${userId}`; await this.client.hSet(key, { userId: userData.userId, activeChatIds: JSON.stringify(userData.activeChatIds), lastActivity: userData.lastActivity.toISOString(), isOnline: userData.isOnline.toString() }); // Set expiration for 2 hours await this.client.expire(key, 7200); } catch (error) { (0, Logger_1.logError)(`Failed to set active user ${userId}`, error); } } async getActiveUser(userId) { try { const key = `active_user:${userId}`; const data = await this.client.hGetAll(key); if (!data.userId) { return null; } return { userId: data.userId, activeChatIds: JSON.parse(data.activeChatIds), lastActivity: new Date(data.lastActivity), isOnline: data.isOnline === 'true' }; } catch (error) { (0, Logger_1.logError)(`Failed to get active user ${userId}`, error); return null; } } async removeActiveUser(userId) { try { const key = `active_user:${userId}`; await this.client.del(key); } catch (error) { (0, Logger_1.logError)(`Failed to remove active user ${userId}`, error); } } async addUserToChat(userId, chatId) { try { const userData = await this.getActiveUser(userId) || { userId, activeChatIds: [], lastActivity: new Date(), isOnline: true }; if (!userData.activeChatIds.includes(chatId)) { userData.activeChatIds.push(chatId); userData.lastActivity = new Date(); await this.setActiveUser(userId, userData); } } catch (error) { (0, Logger_1.logError)(`Failed to add user ${userId} to chat ${chatId}`, error); } } async removeUserFromChat(userId, chatId) { try { const userData = await this.getActiveUser(userId); if (userData) { userData.activeChatIds = userData.activeChatIds.filter(id => id !== chatId); userData.lastActivity = new Date(); await this.setActiveUser(userId, userData); } } catch (error) { (0, Logger_1.logError)(`Failed to remove user ${userId} from chat ${chatId}`, error); } } async getUserActiveChats(userId) { try { const userData = await this.getActiveUser(userId); return userData?.activeChatIds || []; } catch (error) { (0, Logger_1.logError)(`Failed to get active chats for user ${userId}`, error); return []; } } async updateChatActivity(chatId, messageCount) { try { const chatData = await this.getActiveChat(chatId); if (chatData) { chatData.lastActivity = new Date(); if (messageCount !== undefined) { chatData.messageCount = messageCount; } await this.setActiveChat(chatId, chatData); } } catch (error) { (0, Logger_1.logError)(`Failed to update chat activity ${chatId}`, error); } } async getInactiveChats(inactivityMinutes) { try { const cutoffTime = new Date(Date.now() - inactivityMinutes * 60 * 1000); const allChats = await this.getAllActiveChats(); return allChats .filter(chat => chat.lastActivity < cutoffTime) .map(chat => chat.chatId); } catch (error) { (0, Logger_1.logError)('Failed to get inactive chats', error); return []; } } async cleanupInactiveChats(inactivityMinutes) { try { const inactiveChats = await this.getInactiveChats(inactivityMinutes); for (const chatId of inactiveChats) { await this.removeActiveChat(chatId); } return inactiveChats; } catch (error) { (0, Logger_1.logError)('Failed to cleanup inactive chats', error); return []; } } async ping() { try { const result = await this.client.ping(); return result === 'PONG'; } catch (error) { (0, Logger_1.logError)('Redis ping failed', error); return false; } } isRedisConnected() { return this.isConnected; } } exports.RedisService = RedisService; //# sourceMappingURL=RedisService.js.map