fix(mail): add periodic cleanup timers and proper shutdown handling for bounce manager and delivery queue; avoid mutating maps during iteration and prune stale rate-limiter stats to prevent memory growth

This commit is contained in:
2026-03-02 14:06:47 +00:00
parent b465b01790
commit 8851d61466
5 changed files with 82 additions and 23 deletions

View File

@@ -88,7 +88,10 @@ export class BounceManager {
// Store of bounced emails
private bounceStore: BounceRecord[] = [];
// Periodic cleanup timer for old bounce records
private cleanupInterval?: NodeJS.Timeout;
// Cache of recently bounced email addresses to avoid sending to known bad addresses
private bounceCache: LRUCache<string, {
lastBounce: number;
@@ -135,6 +138,15 @@ export class BounceManager {
this.loadSuppressionList().catch(error => {
logger.log('error', `Failed to load suppression list on startup: ${error.message}`);
});
// Start periodic cleanup of old bounce records (every 1 hour, removes records older than 7 days)
this.cleanupInterval = setInterval(() => {
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
const removed = this.clearOldBounceRecords(sevenDaysAgo);
if (removed > 0) {
logger.log('info', `Auto-cleanup removed ${removed} old bounce records`);
}
}, 60 * 60 * 1000);
}
/**
@@ -717,7 +729,7 @@ export class BounceManager {
*/
public clearOldBounceRecords(olderThan: number): number {
let removed = 0;
this.bounceStore = this.bounceStore.filter(bounce => {
if (bounce.timestamp < olderThan) {
removed++;
@@ -725,7 +737,17 @@ export class BounceManager {
}
return true;
});
return removed;
}
/**
* Stop the bounce manager and clear cleanup timers
*/
public stop(): void {
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
this.cleanupInterval = undefined;
}
}
}