fixes for redis event memory leak

This commit is contained in:
Boki 2025-06-10 15:17:47 -04:00
parent 9825e99540
commit fdb8823df7
2 changed files with 39 additions and 14 deletions

View file

@ -2,6 +2,9 @@ import { RedisCache } from './redis-cache';
import { RedisConnectionManager } from './connection-manager'; import { RedisConnectionManager } from './connection-manager';
import type { CacheProvider, CacheOptions } from './types'; import type { CacheProvider, CacheOptions } from './types';
// Cache instances registry to prevent multiple instances with same prefix
const cacheInstances = new Map<string, CacheProvider>();
/** /**
* Create a Redis cache instance with trading-optimized defaults * Create a Redis cache instance with trading-optimized defaults
*/ */
@ -14,6 +17,20 @@ export function createCache(options: Partial<CacheOptions> = {}): CacheProvider
...options ...options
}; };
// For shared connections, reuse cache instances with the same key prefix
if (defaultOptions.shared) {
const cacheKey = `${defaultOptions.keyPrefix}-${defaultOptions.ttl}`;
if (cacheInstances.has(cacheKey)) {
return cacheInstances.get(cacheKey)!;
}
const cache = new RedisCache(defaultOptions);
cacheInstances.set(cacheKey, cache);
return cache;
}
// For non-shared connections, always create new instances
return new RedisCache(defaultOptions); return new RedisCache(defaultOptions);
} }
@ -21,45 +38,39 @@ export function createCache(options: Partial<CacheOptions> = {}): CacheProvider
* Create a cache instance for trading data * Create a cache instance for trading data
*/ */
export function createTradingCache(options: Partial<CacheOptions> = {}): CacheProvider { export function createTradingCache(options: Partial<CacheOptions> = {}): CacheProvider {
const defaultOptions: CacheOptions = { return createCache({
keyPrefix: 'trading:', keyPrefix: 'trading:',
ttl: 3600, // 1 hour default ttl: 3600, // 1 hour default
enableMetrics: true, enableMetrics: true,
shared: true, shared: true,
...options ...options
}; });
return new RedisCache(defaultOptions);
} }
/** /**
* Create a cache for market data with shorter TTL * Create a cache for market data with shorter TTL
*/ */
export function createMarketDataCache(options: Partial<CacheOptions> = {}): CacheProvider { export function createMarketDataCache(options: Partial<CacheOptions> = {}): CacheProvider {
const defaultOptions: CacheOptions = { return createCache({
keyPrefix: 'market:', keyPrefix: 'market:',
ttl: 300, // 5 minutes for market data ttl: 300, // 5 minutes for market data
enableMetrics: true, enableMetrics: true,
shared: true, shared: true,
...options ...options
}; });
return new RedisCache(defaultOptions);
} }
/** /**
* Create a cache for indicators with longer TTL * Create a cache for indicators with longer TTL
*/ */
export function createIndicatorCache(options: Partial<CacheOptions> = {}): CacheProvider { export function createIndicatorCache(options: Partial<CacheOptions> = {}): CacheProvider {
const defaultOptions: CacheOptions = { return createCache({
keyPrefix: 'indicators:', keyPrefix: 'indicators:',
ttl: 1800, // 30 minutes for indicators ttl: 1800, // 30 minutes for indicators
enableMetrics: true, enableMetrics: true,
shared: true, shared: true,
...options ...options
}; });
return new RedisCache(defaultOptions);
} }
// Export types and classes // Export types and classes

View file

@ -42,7 +42,13 @@ export class RedisCache implements CacheProvider {
singleton: options.shared ?? true, // Default to shared connection for cache singleton: options.shared ?? true, // Default to shared connection for cache
}); });
// Only setup event handlers for non-shared connections to avoid memory leaks
if (!(options.shared ?? true)) {
this.setupEventHandlers(); this.setupEventHandlers();
} else {
// For shared connections, just monitor the connection status without adding handlers
this.isConnected = this.redis.status === 'ready';
}
} }
private setupEventHandlers(): void { private setupEventHandlers(): void {
@ -235,6 +241,14 @@ export class RedisCache implements CacheProvider {
} }
isReady(): boolean { isReady(): boolean {
return this.redis.status === 'ready'; // Always check the actual Redis connection status
const ready = this.redis.status === 'ready';
// Update local flag if we're not using shared connection
if (this.isConnected !== ready) {
this.isConnected = ready;
}
return ready;
} }
} }