UNPKG

@yihuangdb/storage-object

Version:

A Node.js storage object layer library using Redis OM

143 lines 5.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RedisConnection = void 0; const redis_1 = require("redis"); const connection_pool_1 = require("./connection-pool"); class RedisConnection { static instance; client = null; options; connectPromise = null; constructor(options = {}) { this.options = { // Only set url if explicitly provided or in environment url: options.url !== undefined ? options.url : process.env.REDIS_URL, host: options.host || 'localhost', port: options.port || 6379, password: options.password, database: options.database || 0, usePool: options.usePool, poolSize: options.poolSize, poolTimeout: options.poolTimeout, idleTimeout: options.idleTimeout, maxRetries: options.maxRetries, retryDelay: options.retryDelay, enableOfflineQueue: options.enableOfflineQueue, connectionName: options.connectionName, }; } static getInstance(options) { if (!RedisConnection.instance) { RedisConnection.instance = new RedisConnection(options); } return RedisConnection.instance; } async connect() { // Use connection pool if enabled if (this.options.usePool !== false) { // If we already have a pooled client, return it if (this.client?.isOpen) { return this.client; } const pool = connection_pool_1.ConnectionPool.getInstance(this.options); const pooledClient = await pool.acquire(); // Store reference for disconnect this.client = pooledClient; return pooledClient; } if (this.client?.isOpen) { return this.client; } // If already connecting, return the existing promise if (this.connectPromise) { return this.connectPromise; } // Create the connection promise this.connectPromise = this.doConnect(); try { const client = await this.connectPromise; return client; } finally { // Clear the promise after completion this.connectPromise = null; } } async doConnect() { const connectionOptions = this.options.url ? { url: this.options.url, name: this.options.connectionName || 'storage-object', } : { socket: { host: this.options.host, port: this.options.port, reconnectStrategy: (retries) => { // Exponential backoff with max delay const maxRetries = this.options.maxRetries || 10; const delay = this.options.retryDelay || 50; if (retries > maxRetries) { return new Error('Max retries reached'); } return Math.min(retries * delay, 3000); }, }, ...(this.options.password && { password: this.options.password }), database: this.options.database, name: this.options.connectionName || 'storage-object', // Enable command queueing for better concurrency commandsQueueMaxLength: 1000, disableOfflineQueue: this.options.enableOfflineQueue === false, }; this.client = (0, redis_1.createClient)(connectionOptions); this.client.on('error', (err) => { console.error('Redis Client Error:', err); }); this.client.on('ready', () => { console.log('Redis client ready'); }); this.client.on('reconnecting', () => { console.log('Redis client reconnecting...'); }); await this.client.connect(); return this.client; } async disconnect() { if (this.client) { try { // If using pool, release the connection instead of closing it if (this.options.usePool !== false) { const pool = connection_pool_1.ConnectionPool.getInstance(this.options); pool.release(this.client); } else if (this.client.isOpen) { await this.client.quit(); } } catch (error) { this.client = null; this.connectPromise = null; throw error; } this.client = null; this.connectPromise = null; } } static async reset() { if (RedisConnection.instance) { await RedisConnection.instance.disconnect(); RedisConnection.instance = null; } // Also reset the connection pool connection_pool_1.ConnectionPool.reset(); } getClient() { if (!this.client?.isOpen) { throw new Error('Redis client is not connected. Call connect() first.'); } return this.client; } } exports.RedisConnection = RedisConnection; //# sourceMappingURL=connection.js.map