fix: enhance retry logic and configuration for HTTP status codes
This commit is contained in:
@@ -45,8 +45,9 @@ export const RETRY_CONFIG = {
|
|||||||
// Backward compat: if value is a number, treated as attempts with RETRY_CONFIG.delayMs
|
// Backward compat: if value is a number, treated as attempts with RETRY_CONFIG.delayMs
|
||||||
export const DEFAULT_RETRY_CONFIG = {
|
export const DEFAULT_RETRY_CONFIG = {
|
||||||
429: { attempts: 0, delayMs: 0 },
|
429: { attempts: 0, delayMs: 0 },
|
||||||
502: { attempts: 1, delayMs: 3000 },
|
502: { attempts: 3, delayMs: 3000 },
|
||||||
503: { attempts: 1, delayMs: 2000 }
|
503: { attempts: 3, delayMs: 2000 },
|
||||||
|
504: { attempts: 2, delayMs: 3000 }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Normalize a retry entry to { attempts, delayMs }
|
// Normalize a retry entry to { attempts, delayMs }
|
||||||
|
|||||||
@@ -104,10 +104,20 @@ export class BaseExecutor {
|
|||||||
let lastError = null;
|
let lastError = null;
|
||||||
let lastStatus = 0;
|
let lastStatus = 0;
|
||||||
const retryAttemptsByUrl = {};
|
const retryAttemptsByUrl = {};
|
||||||
|
|
||||||
// Merge default retry config with provider-specific config
|
// Merge default retry config with provider-specific config
|
||||||
const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...this.config.retry };
|
const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...this.config.retry };
|
||||||
|
|
||||||
|
// Schedule retry via retryConfig[statusKey]. Returns true when caller should `urlIndex--; continue`
|
||||||
|
const tryRetry = async (urlIndex, statusKey, reason) => {
|
||||||
|
const { attempts, delayMs } = resolveRetryEntry(retryConfig[statusKey]);
|
||||||
|
if (attempts <= 0 || retryAttemptsByUrl[urlIndex] >= attempts) return false;
|
||||||
|
retryAttemptsByUrl[urlIndex]++;
|
||||||
|
log?.debug?.("RETRY", `${reason} retry ${retryAttemptsByUrl[urlIndex]}/${attempts} after ${delayMs / 1000}s`);
|
||||||
|
await new Promise(resolve => setTimeout(resolve, delayMs));
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
for (let urlIndex = 0; urlIndex < fallbackCount; urlIndex++) {
|
for (let urlIndex = 0; urlIndex < fallbackCount; urlIndex++) {
|
||||||
const url = this.buildUrl(model, stream, urlIndex, credentials);
|
const url = this.buildUrl(model, stream, urlIndex, credentials);
|
||||||
const transformedBody = this.transformRequest(model, body, stream, credentials);
|
const transformedBody = this.transformRequest(model, body, stream, credentials);
|
||||||
@@ -123,15 +133,7 @@ export class BaseExecutor {
|
|||||||
signal
|
signal
|
||||||
}, proxyOptions);
|
}, proxyOptions);
|
||||||
|
|
||||||
// Retry based on status code config
|
if (await tryRetry(urlIndex, response.status, `status ${response.status}`)) { urlIndex--; continue; }
|
||||||
const { attempts: maxRetries, delayMs } = resolveRetryEntry(retryConfig[response.status]);
|
|
||||||
if (maxRetries > 0 && retryAttemptsByUrl[urlIndex] < maxRetries) {
|
|
||||||
retryAttemptsByUrl[urlIndex]++;
|
|
||||||
log?.debug?.("RETRY", `${response.status} retry ${retryAttemptsByUrl[urlIndex]}/${maxRetries} after ${delayMs / 1000}s`);
|
|
||||||
await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
||||||
urlIndex--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.shouldRetry(response.status, urlIndex)) {
|
if (this.shouldRetry(response.status, urlIndex)) {
|
||||||
log?.debug?.("RETRY", `${response.status} on ${url}, trying fallback ${urlIndex + 1}`);
|
log?.debug?.("RETRY", `${response.status} on ${url}, trying fallback ${urlIndex + 1}`);
|
||||||
@@ -142,6 +144,11 @@ export class BaseExecutor {
|
|||||||
return { response, url, headers, transformedBody };
|
return { response, url, headers, transformedBody };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
lastError = error;
|
lastError = error;
|
||||||
|
if (error.name === "AbortError") throw error;
|
||||||
|
|
||||||
|
// Map network/fetch exceptions to 502 retry config
|
||||||
|
if (await tryRetry(urlIndex, HTTP_STATUS.BAD_GATEWAY, `network "${error.message}"`)) { urlIndex--; continue; }
|
||||||
|
|
||||||
if (urlIndex + 1 < fallbackCount) {
|
if (urlIndex + 1 < fallbackCount) {
|
||||||
log?.debug?.("RETRY", `Error on ${url}, trying fallback ${urlIndex + 1}`);
|
log?.debug?.("RETRY", `Error on ${url}, trying fallback ${urlIndex + 1}`);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user