mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
chore: add proper-lockfile for safe database read/write operations and implement retry logic for file access
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { HTTP_STATUS, RETRY_CONFIG } from "../config/runtimeConfig.js";
|
||||
import { HTTP_STATUS, RETRY_CONFIG, DEFAULT_RETRY_CONFIG } from "../config/runtimeConfig.js";
|
||||
import { proxyAwareFetch } from "../utils/proxyFetch.js";
|
||||
|
||||
/**
|
||||
@@ -81,6 +81,9 @@ export class BaseExecutor {
|
||||
let lastError = null;
|
||||
let lastStatus = 0;
|
||||
const retryAttemptsByUrl = {};
|
||||
|
||||
// Merge default retry config with provider-specific config
|
||||
const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...this.config.retry };
|
||||
|
||||
for (let urlIndex = 0; urlIndex < fallbackCount; urlIndex++) {
|
||||
const url = this.buildUrl(model, stream, urlIndex, credentials);
|
||||
@@ -97,10 +100,11 @@ export class BaseExecutor {
|
||||
signal
|
||||
}, proxyOptions);
|
||||
|
||||
// Retry 429 with fixed delay before falling back to next URL
|
||||
if (response.status === HTTP_STATUS.RATE_LIMITED && retryAttemptsByUrl[urlIndex] < RETRY_CONFIG.maxAttempts) {
|
||||
// Retry based on status code config
|
||||
const maxRetries = retryConfig[response.status] || 0;
|
||||
if (maxRetries > 0 && retryAttemptsByUrl[urlIndex] < maxRetries) {
|
||||
retryAttemptsByUrl[urlIndex]++;
|
||||
log?.debug?.("RETRY", `429 retry ${retryAttemptsByUrl[urlIndex]}/${RETRY_CONFIG.maxAttempts} after ${RETRY_CONFIG.delayMs / 1000}s`);
|
||||
log?.debug?.("RETRY", `${response.status} retry ${retryAttemptsByUrl[urlIndex]}/${maxRetries} after ${RETRY_CONFIG.delayMs / 1000}s`);
|
||||
await new Promise(resolve => setTimeout(resolve, RETRY_CONFIG.delayMs));
|
||||
urlIndex--;
|
||||
continue;
|
||||
|
||||
+33
-16
@@ -3,6 +3,7 @@ import { PROVIDERS } from "../config/providers.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { refreshKiroToken } from "../services/tokenRefresh.js";
|
||||
import { proxyAwareFetch } from "../utils/proxyFetch.js";
|
||||
import { HTTP_STATUS, RETRY_CONFIG, DEFAULT_RETRY_CONFIG } from "../config/runtimeConfig.js";
|
||||
|
||||
/**
|
||||
* KiroExecutor - Executor for Kiro AI (AWS CodeWhisperer)
|
||||
@@ -32,29 +33,45 @@ export class KiroExecutor extends BaseExecutor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom execute for Kiro - handles AWS EventStream binary response
|
||||
* Custom execute for Kiro - handles AWS EventStream binary response with retry support
|
||||
*/
|
||||
async execute({ model, body, stream, credentials, signal, log, proxyOptions = null }) {
|
||||
const url = this.buildUrl(model, stream, 0);
|
||||
const headers = this.buildHeaders(credentials, stream);
|
||||
const transformedBody = this.transformRequest(model, body, stream, credentials);
|
||||
|
||||
// Merge default retry config with provider-specific config
|
||||
const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...this.config.retry };
|
||||
let retryAttempts = 0;
|
||||
|
||||
const response = await proxyAwareFetch(url, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify(transformedBody),
|
||||
signal
|
||||
}, proxyOptions);
|
||||
while (true) {
|
||||
const headers = this.buildHeaders(credentials, stream);
|
||||
|
||||
const response = await proxyAwareFetch(url, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify(transformedBody),
|
||||
signal
|
||||
}, proxyOptions);
|
||||
|
||||
if (!response.ok) {
|
||||
return { response, url, headers, transformedBody };
|
||||
// Check if should retry based on status code
|
||||
const maxRetries = retryConfig[response.status] || 0;
|
||||
if (!response.ok && maxRetries > 0 && retryAttempts < maxRetries) {
|
||||
retryAttempts++;
|
||||
log?.debug?.("RETRY", `${response.status} retry ${retryAttempts}/${maxRetries} after ${RETRY_CONFIG.delayMs / 1000}s`);
|
||||
await new Promise(resolve => setTimeout(resolve, RETRY_CONFIG.delayMs));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
return { response, url, headers, transformedBody };
|
||||
}
|
||||
|
||||
// Success - transform and return
|
||||
// For Kiro, we need to transform the binary EventStream to SSE
|
||||
// Create a TransformStream to convert binary to SSE text
|
||||
const transformedResponse = this.transformEventStreamToSSE(response, model);
|
||||
return { response: transformedResponse, url, headers, transformedBody };
|
||||
}
|
||||
|
||||
// For Kiro, we need to transform the binary EventStream to SSE
|
||||
// Create a TransformStream to convert binary to SSE text
|
||||
const transformedResponse = this.transformEventStreamToSSE(response, model);
|
||||
|
||||
return { response: transformedResponse, url, headers, transformedBody };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user