feat(config): 添加凭证切换最大重试次数配置项

1. 新增 CREDENTIAL_SWITCH_MAX_RETRIES 配置项,默认值为 5
2. 在 config-manager.js 中添加配置初始化
3. 在 config-api.js 中支持配置的读取和更新
4. 在 common.js 中使用该配置控制凭证切换重试次数
5. 在前端配置页面添加对应的输入控件
This commit is contained in:
leonai 2026-01-13 19:00:00 +08:00
parent 948283187c
commit bd8f03b68e
5 changed files with 24 additions and 1 deletions

View file

@ -75,6 +75,7 @@ export async function initializeConfig(args = process.argv.slice(2), configFileP
PROMPT_LOG_MODE: "none",
REQUEST_MAX_RETRIES: 3,
REQUEST_BASE_DELAY: 1000,
CREDENTIAL_SWITCH_MAX_RETRIES: 5, // 坏凭证切换最大重试次数(用于认证错误后切换凭证)
CRON_NEAR_MINUTES: 15,
CRON_REFRESH_TOKEN: false,
PROVIDER_POOLS_FILE_PATH: null, // 新增号池配置文件路径

View file

@ -83,6 +83,7 @@ export async function handleUpdateConfig(req, res, currentConfig) {
if (newConfig.PROMPT_LOG_MODE !== undefined) currentConfig.PROMPT_LOG_MODE = newConfig.PROMPT_LOG_MODE;
if (newConfig.REQUEST_MAX_RETRIES !== undefined) currentConfig.REQUEST_MAX_RETRIES = newConfig.REQUEST_MAX_RETRIES;
if (newConfig.REQUEST_BASE_DELAY !== undefined) currentConfig.REQUEST_BASE_DELAY = newConfig.REQUEST_BASE_DELAY;
if (newConfig.CREDENTIAL_SWITCH_MAX_RETRIES !== undefined) currentConfig.CREDENTIAL_SWITCH_MAX_RETRIES = newConfig.CREDENTIAL_SWITCH_MAX_RETRIES;
if (newConfig.CRON_NEAR_MINUTES !== undefined) currentConfig.CRON_NEAR_MINUTES = newConfig.CRON_NEAR_MINUTES;
if (newConfig.CRON_REFRESH_TOKEN !== undefined) currentConfig.CRON_REFRESH_TOKEN = newConfig.CRON_REFRESH_TOKEN;
if (newConfig.PROVIDER_POOLS_FILE_PATH !== undefined) currentConfig.PROVIDER_POOLS_FILE_PATH = newConfig.PROVIDER_POOLS_FILE_PATH;
@ -131,6 +132,7 @@ export async function handleUpdateConfig(req, res, currentConfig) {
PROMPT_LOG_MODE: currentConfig.PROMPT_LOG_MODE,
REQUEST_MAX_RETRIES: currentConfig.REQUEST_MAX_RETRIES,
REQUEST_BASE_DELAY: currentConfig.REQUEST_BASE_DELAY,
CREDENTIAL_SWITCH_MAX_RETRIES: currentConfig.CREDENTIAL_SWITCH_MAX_RETRIES,
CRON_NEAR_MINUTES: currentConfig.CRON_NEAR_MINUTES,
CRON_REFRESH_TOKEN: currentConfig.CRON_REFRESH_TOKEN,
PROVIDER_POOLS_FILE_PATH: currentConfig.PROVIDER_POOLS_FILE_PATH,

View file

@ -627,7 +627,13 @@ export async function handleContentGenerationRequest(req, res, service, endpoint
// 5. Call the appropriate stream or unary handler, passing the provider info.
// 创建重试上下文,包含 CONFIG 以便在认证错误时切换凭证重试
const retryContext = providerPoolManager ? { CONFIG, currentRetry: 0, maxRetries: 2 } : null;
// 凭证切换重试次数(默认 5可在配置中自定义更大的值
// 注意:这与底层的 429/5xx 重试REQUEST_MAX_RETRIES是不同层次的重试机制
// - 底层重试:同一凭证遇到 429/5xx 时的重试
// - 凭证切换重试:凭证被标记不健康后切换到其他凭证
// 当没有不同的健康凭证可用时,重试会自动停止
const credentialSwitchMaxRetries = CONFIG.CREDENTIAL_SWITCH_MAX_RETRIES || 5;
const retryContext = providerPoolManager ? { CONFIG, currentRetry: 0, maxRetries: credentialSwitchMaxRetries } : null;
if (isStream) {
await handleStreamRequest(res, service, model, processedRequestBody, fromProvider, toProvider, CONFIG.PROMPT_LOG_MODE, PROMPT_LOG_FILENAME, providerPoolManager, actualUuid, actualCustomName, retryContext);

View file

@ -90,6 +90,11 @@ async function loadConfiguration() {
if (promptLogModeEl) promptLogModeEl.value = data.PROMPT_LOG_MODE || 'none';
if (requestMaxRetriesEl) requestMaxRetriesEl.value = data.REQUEST_MAX_RETRIES || 3;
if (requestBaseDelayEl) requestBaseDelayEl.value = data.REQUEST_BASE_DELAY || 1000;
// 坏凭证切换最大重试次数
const credentialSwitchMaxRetriesEl = document.getElementById('credentialSwitchMaxRetries');
if (credentialSwitchMaxRetriesEl) credentialSwitchMaxRetriesEl.value = data.CREDENTIAL_SWITCH_MAX_RETRIES || 5;
if (cronNearMinutesEl) cronNearMinutesEl.value = data.CRON_NEAR_MINUTES || 1;
if (cronRefreshTokenEl) cronRefreshTokenEl.checked = data.CRON_REFRESH_TOKEN || false;
if (providerPoolsFilePathEl) providerPoolsFilePathEl.value = data.PROVIDER_POOLS_FILE_PATH;
@ -187,6 +192,7 @@ async function saveConfiguration() {
config.PROMPT_LOG_MODE = document.getElementById('promptLogMode')?.value || '';
config.REQUEST_MAX_RETRIES = parseInt(document.getElementById('requestMaxRetries')?.value || 3);
config.REQUEST_BASE_DELAY = parseInt(document.getElementById('requestBaseDelay')?.value || 1000);
config.CREDENTIAL_SWITCH_MAX_RETRIES = parseInt(document.getElementById('credentialSwitchMaxRetries')?.value || 5);
config.CRON_NEAR_MINUTES = parseInt(document.getElementById('cronNearMinutes')?.value || 1);
config.CRON_REFRESH_TOKEN = document.getElementById('cronRefreshToken')?.checked || false;
config.PROVIDER_POOLS_FILE_PATH = document.getElementById('providerPoolsFilePath')?.value || '';

View file

@ -162,6 +162,14 @@
</div>
</div>
<div class="config-row">
<div class="form-group">
<label for="credentialSwitchMaxRetries" data-i18n="config.advanced.credentialSwitchMaxRetries">坏凭证切换最大重试次数</label>
<input type="number" id="credentialSwitchMaxRetries" class="form-control" min="1" max="50" value="5">
<small class="form-text" data-i18n="config.advanced.credentialSwitchMaxRetriesNote">认证错误(401/403)后切换凭证的最大重试次数,默认 5 次</small>
</div>
</div>
<div class="config-row">
<div class="form-group">
<label for="cronNearMinutes" data-i18n="config.advanced.cronInterval">OAuth令牌刷新间隔(分钟)</label>