refactor(grok): 移除流式请求重试逻辑并简化错误处理

移除 generateContentStream 方法中的重试机制及相关辅助方法,将错误处理简化为仅处理认证错误。版本号更新至 2.11.7.1。
This commit is contained in:
hex2077 2026-03-20 22:45:46 +08:00
parent 46038a5459
commit 807e3670b1
2 changed files with 9 additions and 66 deletions

View file

@ -1 +1 @@
2.11.7 2.11.7.1

View file

@ -3,7 +3,7 @@ import logger from '../../utils/logger.js';
import * as http from 'http'; import * as http from 'http';
import * as https from 'https'; import * as https from 'https';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { MODEL_PROTOCOL_PREFIX, isRetryableNetworkError } from '../../utils/common.js'; import { MODEL_PROTOCOL_PREFIX } from '../../utils/common.js';
import { getProviderModels } from '../provider-models.js'; import { getProviderModels } from '../provider-models.js';
import { configureAxiosProxy, configureTLSSidecar } from '../../utils/proxy-utils.js'; import { configureAxiosProxy, configureTLSSidecar } from '../../utils/proxy-utils.js';
import { MODEL_PROVIDER } from '../../utils/common.js'; import { MODEL_PROVIDER } from '../../utils/common.js';
@ -85,34 +85,6 @@ export class GrokApiService {
this.lastSyncAt = null; this.lastSyncAt = null;
} }
getMaxRequestRetries() {
const requestMaxRetries = Number.parseInt(this.config.REQUEST_MAX_RETRIES, 10);
if (Number.isFinite(requestMaxRetries) && requestMaxRetries > 0) {
return requestMaxRetries;
}
return 3;
}
classifyApiError(error) {
const status = error.response?.status;
const errorCode = error.code;
const errorMessage = error.message || '';
const isNetworkError = isRetryableNetworkError(error);
if (status === 401 || status === 403) {
error.shouldSwitchCredential = true;
error.message = 'Grok authentication failed (SSO token invalid or expired)';
} else if (isNetworkError) {
// Network jitter or request timeout should not immediately degrade account health.
// Let the upper retry layer switch credential without incrementing the provider error count.
error.shouldSwitchCredential = true;
error.skipErrorCount = true;
}
return { status, errorCode, errorMessage, isNetworkError };
}
async setupNsfw() { async setupNsfw() {
if (this.nsfwSetupDone) return; if (this.nsfwSetupDone) return;
try { try {
@ -509,11 +481,7 @@ export class GrokApiService {
try { return (await axios(axiosConfig)).data; } catch (error) { return null; } try { return (await axios(axiosConfig)).data; } catch (error) { return null; }
} }
async * generateContentStream(model, requestBody, retryCount = 0) { async * generateContentStream(model, requestBody) {
const maxRetries = this.getMaxRequestRetries();
const baseDelay = this.config.REQUEST_BASE_DELAY || 1000;
let hasYieldedData = false;
if (this.converter) { if (this.converter) {
if (this.uuid) this.converter.setUuid(this.uuid); if (this.uuid) this.converter.setUuid(this.uuid);
if (requestBody._requestBaseUrl) this.converter.setRequestBaseUrl(requestBody._requestBaseUrl); if (requestBody._requestBaseUrl) this.converter.setRequestBaseUrl(requestBody._requestBaseUrl);
@ -630,42 +598,17 @@ export class GrokApiService {
} }
} }
} }
hasYieldedData = true;
yield json; yield json;
} catch (e) {} } catch (e) {}
} }
yield { result: { response: { isDone: true, responseId: lastResponseId, _requestBaseUrl: reqBaseUrl, _uuid: this.uuid } } }; yield { result: { response: { isDone: true, responseId: lastResponseId, _requestBaseUrl: reqBaseUrl, _uuid: this.uuid } } };
} catch (error) { } catch (error) { this.handleApiError(error); }
const { status, errorCode, errorMessage, isNetworkError } = this.classifyApiError(error); }
const canRetryInRequest = !hasYieldedData && retryCount < maxRetries;
if (status === 429 && canRetryInRequest) { handleApiError(error) {
const delay = baseDelay * Math.pow(2, retryCount); const status = error.response?.status;
logger.info(`[Grok API] Received 429 during stream. Retrying in ${delay}ms... (attempt ${retryCount + 1}/${maxRetries})`); if (status === 401 || status === 403) { error.shouldSwitchCredential = true; error.message = 'Grok authentication failed (SSO token invalid or expired)'; }
await new Promise(resolve => setTimeout(resolve, delay)); throw error;
yield* this.generateContentStream(model, requestBody, retryCount + 1);
return;
}
if (status >= 500 && status < 600 && canRetryInRequest) {
const delay = baseDelay * Math.pow(2, retryCount);
logger.info(`[Grok API] Received ${status} server error during stream. Retrying in ${delay}ms... (attempt ${retryCount + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
yield* this.generateContentStream(model, requestBody, retryCount + 1);
return;
}
if (isNetworkError && canRetryInRequest) {
const delay = baseDelay * Math.pow(2, retryCount);
const errorIdentifier = errorCode || errorMessage.substring(0, 50);
logger.info(`[Grok API] Network error (${errorIdentifier}) during stream. Retrying in ${delay}ms... (attempt ${retryCount + 1}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, delay));
yield* this.generateContentStream(model, requestBody, retryCount + 1);
return;
}
throw error;
}
} }
async listModels() { async listModels() {