perf: stability and performance improvements across proxy
- Add exponential backoff (200ms-2s) between retry attempts - Fix session retry bug: rotate proxy before retry to avoid same proxy - Fix ACTIVE_READERS memory leak: release reader on stream done/error - Make closeAllActiveReaders async with proper await - WebSocket backpressure: pause upstream forwarding at 512KB buffer - Optimize rate-limiter pruneTimestamps: avoid array reallocation - Batch stream chunks (8 per yield) to reduce event loop overhead - Add periodic cooldown cleanup in ProxyPool (30s interval) - Extract shared wrapStreamWithCleanup utility to reduce duplication - Fix fetchViaCurl temp file cleanup with proper unlink() - Add missing ipv6Source overload to AI proxy handlers
This commit is contained in:
@@ -41,6 +41,8 @@ export class ProxyPool {
|
||||
/** host:port::model -> expiry epoch ms */
|
||||
private cooldowns = new Map<string, number>();
|
||||
private cooldownDuration = 60000; // default 60s
|
||||
/** Periodic cleanup timer for expired cooldowns */
|
||||
private cleanupTimer: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
// -- Load --------------------------------------------------------------------
|
||||
|
||||
@@ -126,9 +128,29 @@ export class ProxyPool {
|
||||
this.currentIndex = 0;
|
||||
this.failures.clear();
|
||||
|
||||
// Start periodic cooldown cleanup (every 30s)
|
||||
this.startCooldownCleanup();
|
||||
|
||||
logPool(`loaded ${this.proxies.length} proxies from ${source}`);
|
||||
}
|
||||
|
||||
/** Periodically clean up expired cooldown entries to prevent memory leaks. */
|
||||
private startCooldownCleanup(): void {
|
||||
if (this.cleanupTimer) return;
|
||||
this.cleanupTimer = setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [key, expiry] of this.cooldowns) {
|
||||
if (now > expiry) {
|
||||
this.cooldowns.delete(key);
|
||||
}
|
||||
}
|
||||
}, 30_000); // every 30s
|
||||
// Allow process to exit even if timer is active
|
||||
if (this.cleanupTimer && typeof this.cleanupTimer === "object" && "unref" in this.cleanupTimer) {
|
||||
this.cleanupTimer.unref();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience -- load from a path or skip.
|
||||
* Returns `true` if proxies were loaded.
|
||||
|
||||
Reference in New Issue
Block a user