fix: exhaust all proxies then direct fallback before giving up

fetchWithRetry:
- Dynamically calculate maxAttempts = pool.size + 1 (direct fallback)
- Try every proxy in pool via rotation, then direct as last resort
- Only classify as error when even direct produces no response

fetchWithSessionRetry:
- Default maxRetries = sessionPool.size + 1 instead of hardcoded 3
- Try pool.size proxy attempts (each on a different proxy via rotateNow),
  then 1 direct attempt (no proxy) before giving up
- Only classify as error if direct also returns no response

ProxyPool.rotate():
- Skip proxies that have exceeded the failure threshold (isFailed)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
MythEclipse
2026-06-17 04:45:30 +07:00
co-authored by Claude
parent f1943353ef
commit 283ed26231
2 changed files with 58 additions and 27 deletions
+20 -5
View File
@@ -138,15 +138,30 @@ export class ProxyPool {
/**
* Advance to the next proxy (round-robin, wraps around).
* Returns the new current proxy or `null` if the pool is empty.
* Skips proxies that have exceeded the failure threshold.
* Returns the new current proxy or `null` if the pool is empty or
* all proxies are failed.
*/
rotate(): ProxyEntry | null {
if (this.proxies.length === 0) return null;
const oldIndex = this.currentIndex;
this.currentIndex = (this.currentIndex + 1) % this.proxies.length;
const entry = this.proxies[this.currentIndex] ?? null;
logPool(`rotate ${oldIndex} -> ${this.currentIndex}`, { host: entry?.host });
return entry;
const startIndex = this.currentIndex;
// Keep advancing until we find a non-failed proxy or loop back
let checked = 0;
do {
this.currentIndex = (this.currentIndex + 1) % this.proxies.length;
checked++;
if (!this.isFailed()) {
const entry = this.proxies[this.currentIndex] ?? null;
logPool(`rotate ${oldIndex} -> ${this.currentIndex} (skipped ${checked - 1} failed)`);
return entry;
}
} while (this.currentIndex !== startIndex && checked <= this.proxies.length);
// All proxies failed — stay on current but log it
logPool(`rotate ${oldIndex} -> ${this.currentIndex} (all proxies failed)`);
return this.proxies[this.currentIndex] ?? null;
}
/**