UNPKG

pallas-db

Version:
180 lines (179 loc) 6.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisStorage = void 0; const redis_1 = require("redis"); // Redis storage management class RedisStorage { client; isConnected = false; connectionPromise = null; constructor(options = {}) { const redisConfig = { socket: { host: options.host || 'localhost', port: options.port || 6379 } }; if (options.password) { redisConfig.password = options.password; } if (options.database !== undefined) { redisConfig.database = options.database; } if (options.url) { // If URL is provided, use it instead of individual options this.client = (0, redis_1.createClient)({ url: options.url }); } else { this.client = (0, redis_1.createClient)(redisConfig); } // Handle Redis connection events this.client.on('error', (err) => { console.error('Redis Client Error:', err); this.isConnected = false; }); this.client.on('connect', () => { this.isConnected = true; }); this.client.on('disconnect', () => { this.isConnected = false; }); } async ensureConnection() { if (this.isConnected) return; if (this.connectionPromise) { return this.connectionPromise; } this.connectionPromise = this.client.connect().then(() => undefined); await this.connectionPromise; this.connectionPromise = null; } getTableKey(tableName, id) { return `${tableName}:${id}`; } getTablePattern(tableName) { return `${tableName}:*`; } async getRecord(tableName, id) { await this.ensureConnection(); const key = this.getTableKey(tableName, id); const value = await this.client.get(key); if (value === null || value === undefined) return undefined; const stringValue = String(value); try { return JSON.parse(stringValue); } catch { return stringValue; } } async setTableData(tableName, id, value) { await this.ensureConnection(); const key = this.getTableKey(tableName, id); const serializedValue = JSON.stringify(value); await this.client.set(key, serializedValue); } async deleteTableKey(tableName, id) { await this.ensureConnection(); const key = this.getTableKey(tableName, id); await this.client.del(key); } async clearTable(tableName) { await this.ensureConnection(); const pattern = this.getTablePattern(tableName); const keys = await this.client.keys(pattern); if (keys.length > 0) { // Convert keys to strings and delete them one by one for (const key of keys) { await this.client.del(String(key)); } } } async hasKey(tableName, id) { await this.ensureConnection(); const key = this.getTableKey(tableName, id); const exists = await this.client.exists(key); return exists === 1; } async getAllFromTable(tableName) { await this.ensureConnection(); const pattern = this.getTablePattern(tableName); const keys = await this.client.keys(pattern); const results = []; for (const key of keys) { const keyStr = String(key); // Ensure key is string const id = keyStr.substring(tableName.length + 1); // Remove table prefix const value = await this.client.get(keyStr); if (value !== null && value !== undefined) { // Handle case where Redis returns an empty object if (typeof value === 'object' && Object.keys(value).length === 0) { continue; // Skip empty objects } const stringValue = typeof value === 'string' ? value : JSON.stringify(value); try { const parsedValue = JSON.parse(stringValue); results.push({ id, value: parsedValue }); } catch { results.push({ id, value: stringValue }); } } } return results; } async getStats(tables) { await this.ensureConnection(); const stats = {}; for (const tableName of tables) { const pattern = this.getTablePattern(tableName); const keys = await this.client.keys(pattern); stats[tableName] = keys.length; } return stats; } async repair(tables, validateKey, validateValue) { await this.ensureConnection(); const deletedKeys = []; for (const tableName of tables) { const pattern = this.getTablePattern(tableName); const keys = await this.client.keys(pattern); for (const key of keys) { const keyStr = String(key); // Ensure key is string const id = keyStr.substring(tableName.length + 1); const value = await this.client.get(keyStr); if (value !== null && value !== undefined) { // Handle case where Redis returns an empty object if (typeof value === 'object' && Object.keys(value).length === 0) { // Empty object is invalid, delete the key await this.client.del(keyStr); deletedKeys.push(`${tableName}.${id}`); continue; } const stringValue = typeof value === 'string' ? value : JSON.stringify(value); try { const parsedValue = JSON.parse(stringValue); if (!validateKey(id) || !validateValue(parsedValue)) { await this.client.del(keyStr); deletedKeys.push(`${tableName}.${id}`); } } catch { // Invalid JSON, delete the key await this.client.del(keyStr); deletedKeys.push(`${tableName}.${id}`); } } } } return deletedKeys; } async disconnect() { if (this.isConnected) { await this.client.disconnect(); this.isConnected = false; } } } exports.RedisStorage = RedisStorage;