fix(cleanup): prevent event listener and log stream leaks, tighten smartProxy connection timeouts, and improve graceful shutdown behavior

This commit is contained in:
2026-02-26 17:14:51 +00:00
parent cfc4cf378f
commit 0c4e28455e
9 changed files with 157 additions and 75 deletions

View File

@@ -476,6 +476,12 @@ export class DcRouter {
...this.options.smartProxyConfig,
routes,
acme: acmeConfig,
// Tighter connection timeouts to prevent connection buildup
socketTimeout: 300_000, // 5 min idle socket timeout
inactivityTimeout: 600_000, // 10 min inactivity timeout
keepAliveInactivityMultiplier: 3, // keep-alive idle = 30 min (10min * 3)
extendedKeepAliveLifetime: 3_600_000, // keep-alive connections live max 1 hour
maxConnectionLifetime: 14_400_000, // absolute max connection lifetime 4 hours
certStore: {
loadAll: async () => {
const keys = await this.storageManager.list('/proxy-certs/');
@@ -903,6 +909,20 @@ export class DcRouter {
await this.opsServer.stop();
try {
// Remove event listeners before stopping services to prevent leaks
if (this.smartProxy) {
this.smartProxy.removeAllListeners();
}
if (this.emailServer) {
if ((this.emailServer as any).deliverySystem) {
(this.emailServer as any).deliverySystem.removeAllListeners();
}
this.emailServer.removeAllListeners();
}
if (this.dnsServer) {
this.dnsServer.removeAllListeners();
}
// Stop all services in parallel for faster shutdown
await Promise.all([
// Stop cache cleaner if running
@@ -976,10 +996,11 @@ export class DcRouter {
public async updateSmartProxyConfig(config: plugins.smartproxy.ISmartProxyOptions): Promise<void> {
// Stop existing SmartProxy if running
if (this.smartProxy) {
this.smartProxy.removeAllListeners();
await this.smartProxy.stop();
this.smartProxy = undefined;
}
// Update configuration
this.options.smartProxyConfig = config;
@@ -1103,6 +1124,11 @@ export class DcRouter {
try {
// Stop the unified email server which contains all components
if (this.emailServer) {
// Remove listeners before stopping to prevent leaks on config update cycles
if ((this.emailServer as any).deliverySystem) {
(this.emailServer as any).deliverySystem.removeAllListeners();
}
this.emailServer.removeAllListeners();
await this.emailServer.stop();
logger.log('info', 'Unified email server stopped');
this.emailServer = undefined;