19.6.1
This commit is contained in:
@ -30,6 +30,9 @@ export class FunctionCache {
|
||||
// Logger
|
||||
private logger: ILogger;
|
||||
|
||||
// Cleanup interval timer
|
||||
private cleanupInterval: NodeJS.Timeout | null = null;
|
||||
|
||||
/**
|
||||
* Creates a new function cache
|
||||
*
|
||||
@ -48,7 +51,12 @@ export class FunctionCache {
|
||||
this.defaultTtl = options.defaultTtl || 5000; // 5 seconds default
|
||||
|
||||
// Start the cache cleanup timer
|
||||
setInterval(() => this.cleanupCache(), 30000); // Cleanup every 30 seconds
|
||||
this.cleanupInterval = setInterval(() => this.cleanupCache(), 30000); // Cleanup every 30 seconds
|
||||
|
||||
// Make sure the interval doesn't keep the process alive
|
||||
if (this.cleanupInterval.unref) {
|
||||
this.cleanupInterval.unref();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -256,4 +264,16 @@ export class FunctionCache {
|
||||
this.portCache.clear();
|
||||
this.logger.info('Function cache cleared');
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the cache and cleanup resources
|
||||
*/
|
||||
public destroy(): void {
|
||||
if (this.cleanupInterval) {
|
||||
clearInterval(this.cleanupInterval);
|
||||
this.cleanupInterval = null;
|
||||
}
|
||||
this.clearCache();
|
||||
this.logger.debug('Function cache destroyed');
|
||||
}
|
||||
}
|
@ -464,6 +464,11 @@ export class HttpProxy implements IMetricsTracker {
|
||||
// Stop WebSocket handler
|
||||
this.webSocketHandler.shutdown();
|
||||
|
||||
// Destroy request handler (cleans up intervals and caches)
|
||||
if (this.requestHandler && typeof this.requestHandler.destroy === 'function') {
|
||||
this.requestHandler.destroy();
|
||||
}
|
||||
|
||||
// Close all tracked sockets
|
||||
const socketCleanupPromises = this.socketMap.getArray().map(socket =>
|
||||
cleanupSocket(socket, 'http-proxy-stop', { immediate: true })
|
||||
|
@ -42,6 +42,9 @@ export class RequestHandler {
|
||||
|
||||
// Security manager for IP filtering, rate limiting, etc.
|
||||
public securityManager: SecurityManager;
|
||||
|
||||
// Rate limit cleanup interval
|
||||
private rateLimitCleanupInterval: NodeJS.Timeout | null = null;
|
||||
|
||||
constructor(
|
||||
private options: IHttpProxyOptions,
|
||||
@ -54,9 +57,14 @@ export class RequestHandler {
|
||||
this.securityManager = new SecurityManager(this.logger);
|
||||
|
||||
// Schedule rate limit cleanup every minute
|
||||
setInterval(() => {
|
||||
this.rateLimitCleanupInterval = setInterval(() => {
|
||||
this.securityManager.cleanupExpiredRateLimits();
|
||||
}, 60000);
|
||||
|
||||
// Make sure the interval doesn't keep the process alive
|
||||
if (this.rateLimitCleanupInterval.unref) {
|
||||
this.rateLimitCleanupInterval.unref();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -741,4 +749,27 @@ export class RequestHandler {
|
||||
stream.end('Not Found: No route configuration for this request');
|
||||
if (this.metricsTracker) this.metricsTracker.incrementFailedRequests();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup resources and stop intervals
|
||||
*/
|
||||
public destroy(): void {
|
||||
if (this.rateLimitCleanupInterval) {
|
||||
clearInterval(this.rateLimitCleanupInterval);
|
||||
this.rateLimitCleanupInterval = null;
|
||||
}
|
||||
|
||||
// Close all HTTP/2 sessions
|
||||
for (const [key, session] of this.h2Sessions) {
|
||||
session.close();
|
||||
}
|
||||
this.h2Sessions.clear();
|
||||
|
||||
// Clear function cache if it has a destroy method
|
||||
if (this.functionCache && typeof this.functionCache.destroy === 'function') {
|
||||
this.functionCache.destroy();
|
||||
}
|
||||
|
||||
this.logger.debug('RequestHandler destroyed');
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ export class MetricsCollector implements IProxyStatsExtended {
|
||||
// RPS tracking (the only state we need to maintain)
|
||||
private requestTimestamps: number[] = [];
|
||||
private readonly RPS_WINDOW_SIZE = 60000; // 1 minute window
|
||||
private readonly MAX_TIMESTAMPS = 5000; // Maximum timestamps to keep
|
||||
|
||||
// Optional caching for performance
|
||||
private cachedMetrics: {
|
||||
@ -148,11 +149,14 @@ export class MetricsCollector implements IProxyStatsExtended {
|
||||
* Record a new request for RPS tracking
|
||||
*/
|
||||
public recordRequest(): void {
|
||||
this.requestTimestamps.push(Date.now());
|
||||
const now = Date.now();
|
||||
this.requestTimestamps.push(now);
|
||||
|
||||
// Prevent unbounded growth
|
||||
if (this.requestTimestamps.length > 10000) {
|
||||
this.cleanupOldRequests();
|
||||
// Prevent unbounded growth - clean up more aggressively
|
||||
if (this.requestTimestamps.length > this.MAX_TIMESTAMPS) {
|
||||
// Keep only timestamps within the window
|
||||
const cutoff = now - this.RPS_WINDOW_SIZE;
|
||||
this.requestTimestamps = this.requestTimestamps.filter(ts => ts > cutoff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import { TlsManager } from './tls-manager.js';
|
||||
import { HttpProxyBridge } from './http-proxy-bridge.js';
|
||||
import { TimeoutManager } from './timeout-manager.js';
|
||||
import { SharedRouteManager as RouteManager } from '../../core/routing/route-manager.js';
|
||||
import { cleanupSocket, createIndependentSocketHandlers, setupSocketHandlers, createSocketWithErrorHandler, setupBidirectionalForwarding } from '../../core/utils/socket-utils.js';
|
||||
import { cleanupSocket, setupSocketHandlers, createSocketWithErrorHandler, setupBidirectionalForwarding } from '../../core/utils/socket-utils.js';
|
||||
import { WrappedSocket } from '../../core/models/wrapped-socket.js';
|
||||
import { getUnderlyingSocket } from '../../core/models/socket-types.js';
|
||||
import { ProxyProtocolParser } from '../../core/utils/proxy-protocol.js';
|
||||
@ -21,8 +21,9 @@ import { ProxyProtocolParser } from '../../core/utils/proxy-protocol.js';
|
||||
export class RouteConnectionHandler {
|
||||
private settings: ISmartProxyOptions;
|
||||
|
||||
// Cache for route contexts to avoid recreation
|
||||
private routeContextCache: Map<string, IRouteContext> = new Map();
|
||||
// Note: Route context caching was considered but not implemented
|
||||
// as route contexts are lightweight and should be created fresh
|
||||
// for each connection to ensure accurate context data
|
||||
|
||||
// RxJS Subject for new connections
|
||||
public newConnectionSubject = new plugins.smartrx.rxjs.Subject<IConnectionRecord>();
|
||||
@ -730,8 +731,7 @@ export class RouteConnectionHandler {
|
||||
routeId: route.id,
|
||||
});
|
||||
|
||||
// Cache the context for potential reuse
|
||||
this.routeContextCache.set(connectionId, routeContext);
|
||||
// Note: Route contexts are not cached to ensure fresh data for each connection
|
||||
|
||||
// Determine host using function or static value
|
||||
let targetHost: string | string[];
|
||||
|
Reference in New Issue
Block a user