273 lines
9.3 KiB
JavaScript
273 lines
9.3 KiB
JavaScript
"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
|