refactor(providers): 重构 Codex 认证刷新机制以支持后台异步刷新
- 将直接调用 refreshAccessToken 改为调用 initializeAuth(true) 以统一认证流程 - 新增 triggerBackgroundRefresh 方法,在 token 即将过期或收到 401 时异步触发刷新 - 移除多处重复的 PoolManager 标记逻辑,统一由 triggerBackgroundRefresh 处理 - 优化 initializeAuth 方法,仅在需要时加载凭证,避免不必要的阻塞 - 更新版本号至 2.11.0
This commit is contained in:
parent
0631d0db05
commit
f2f02b365f
3 changed files with 38 additions and 55 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
2.10.9.3
|
||||
2.11.0
|
||||
|
|
|
|||
|
|
@ -574,7 +574,7 @@ export class CodexApiServiceAdapter extends ApiServiceAdapter {
|
|||
}
|
||||
if (this.isExpiryDateNear()) {
|
||||
logger.info(`[Codex] Expiry date is near, refreshing token...`);
|
||||
await this.codexApiService.refreshAccessToken();
|
||||
await this.codexApiService.initializeAuth(true);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
|
@ -584,7 +584,7 @@ export class CodexApiServiceAdapter extends ApiServiceAdapter {
|
|||
await this.codexApiService.initialize();
|
||||
}
|
||||
logger.info(`[Codex] Force refreshing token...`);
|
||||
return this.codexApiService.refreshAccessToken();
|
||||
return this.codexApiService.initializeAuth(true);
|
||||
}
|
||||
|
||||
isExpiryDateNear() {
|
||||
|
|
|
|||
|
|
@ -99,10 +99,9 @@ export class CodexApiService {
|
|||
this.last_refresh = creds.last_refresh || this.last_refresh;
|
||||
this.expiresAt = new Date(creds.expired); // 注意:字段名是 expired
|
||||
|
||||
// 检查 token 是否需要刷新
|
||||
// 检查 token 是否需要刷新(异步触发,不阻塞加载)
|
||||
if (this.isExpiryDateNear()) {
|
||||
logger.info('[Codex] Token expiring soon, refreshing...');
|
||||
await this.refreshAccessToken();
|
||||
this.triggerBackgroundRefresh();
|
||||
}
|
||||
|
||||
this.isInitialized = true;
|
||||
|
|
@ -116,9 +115,6 @@ export class CodexApiService {
|
|||
* 初始化认证并执行必要刷新
|
||||
*/
|
||||
async initializeAuth(forceRefresh = false) {
|
||||
// 首先执行基础凭证加载
|
||||
await this.loadCredentials();
|
||||
|
||||
// 检查 token 是否需要刷新
|
||||
const needsRefresh = forceRefresh;
|
||||
|
||||
|
|
@ -126,7 +122,11 @@ export class CodexApiService {
|
|||
return;
|
||||
}
|
||||
|
||||
// 首先执行基础凭证加载
|
||||
await this.loadCredentials();
|
||||
|
||||
// 只有在明确要求刷新,或者 AccessToken 缺失时,才执行刷新
|
||||
// 注意:在 V2 架构下,此方法主要由 PoolManager 的后台队列调用
|
||||
if (needsRefresh || !this.accessToken) {
|
||||
if (!this.refreshToken) {
|
||||
throw new Error('Codex credentials not found. Please authenticate first using OAuth.');
|
||||
|
|
@ -136,6 +136,19 @@ export class CodexApiService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台异步刷新 token(不阻塞当前请求)
|
||||
*/
|
||||
triggerBackgroundRefresh() {
|
||||
const poolManager = getProviderPoolManager();
|
||||
if (poolManager && this.uuid) {
|
||||
logger.info(`[Codex] Token is near expiry, marking credential ${this.uuid} for background refresh`);
|
||||
poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, {
|
||||
uuid: this.uuid
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成内容(非流式)
|
||||
*/
|
||||
|
|
@ -160,15 +173,9 @@ export class CodexApiService {
|
|||
delete requestBody._requestBaseUrl;
|
||||
}
|
||||
|
||||
// 检查 token 是否即将过期,如果是则推送到刷新队列
|
||||
// 检查 token 是否即将过期,如果是则触发后台异步刷新
|
||||
if (this.isExpiryDateNear()) {
|
||||
const poolManager = getProviderPoolManager();
|
||||
if (poolManager && this.uuid) {
|
||||
logger.info(`[Codex] Token is near expiry, marking credential ${this.uuid} for refresh`);
|
||||
poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, {
|
||||
uuid: this.uuid
|
||||
});
|
||||
}
|
||||
this.triggerBackgroundRefresh();
|
||||
}
|
||||
|
||||
const url = `${this.baseUrl}/responses`;
|
||||
|
|
@ -194,17 +201,11 @@ export class CodexApiService {
|
|||
return this.parseNonStreamResponse(response.data);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 401) {
|
||||
logger.info('[Codex] Received 401. Triggering background refresh via PoolManager...');
|
||||
logger.info('[Codex] Received 401. Triggering background refresh...');
|
||||
|
||||
// 标记当前凭证为不健康(会自动进入刷新队列)
|
||||
const poolManager = getProviderPoolManager();
|
||||
if (poolManager && this.uuid) {
|
||||
logger.info(`[Codex] Marking credential ${this.uuid} as needs refresh. Reason: 401 Unauthorized`);
|
||||
poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, {
|
||||
uuid: this.uuid
|
||||
});
|
||||
error.credentialMarkedUnhealthy = true;
|
||||
}
|
||||
// 触发后台异步刷新
|
||||
this.triggerBackgroundRefresh();
|
||||
error.credentialMarkedUnhealthy = true;
|
||||
|
||||
// Mark error for credential switch without recording error count
|
||||
error.shouldSwitchCredential = true;
|
||||
|
|
@ -241,15 +242,9 @@ export class CodexApiService {
|
|||
delete requestBody._requestBaseUrl;
|
||||
}
|
||||
|
||||
// 检查 token 是否即将过期,如果是则推送到刷新队列
|
||||
// 检查 token 是否即将过期,如果是则触发后台异步刷新
|
||||
if (this.isExpiryDateNear()) {
|
||||
const poolManager = getProviderPoolManager();
|
||||
if (poolManager && this.uuid) {
|
||||
logger.info(`[Codex] Token is near expiry, marking credential ${this.uuid} for refresh`);
|
||||
poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, {
|
||||
uuid: this.uuid
|
||||
});
|
||||
}
|
||||
this.triggerBackgroundRefresh();
|
||||
}
|
||||
|
||||
const url = `${this.baseUrl}/responses`;
|
||||
|
|
@ -275,17 +270,11 @@ export class CodexApiService {
|
|||
yield* this.parseSSEStream(response.data);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 401) {
|
||||
logger.info('[Codex] Received 401 during stream. Triggering background refresh via PoolManager...');
|
||||
logger.info('[Codex] Received 401 during stream. Triggering background refresh...');
|
||||
|
||||
// 标记当前凭证为不健康
|
||||
const poolManager = getProviderPoolManager();
|
||||
if (poolManager && this.uuid) {
|
||||
logger.info(`[Codex] Marking credential ${this.uuid} as needs refresh. Reason: 401 Unauthorized in stream`);
|
||||
poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, {
|
||||
uuid: this.uuid
|
||||
});
|
||||
error.credentialMarkedUnhealthy = true;
|
||||
}
|
||||
// 触发后台异步刷新
|
||||
this.triggerBackgroundRefresh();
|
||||
error.credentialMarkedUnhealthy = true;
|
||||
|
||||
// Mark error for credential switch without recording error count
|
||||
error.shouldSwitchCredential = true;
|
||||
|
|
@ -731,17 +720,11 @@ export class CodexApiService {
|
|||
return result;
|
||||
} catch (error) {
|
||||
if (error.response?.status === 401) {
|
||||
logger.info('[Codex] Received 401 during getUsageLimits. Triggering background refresh via PoolManager...');
|
||||
logger.info('[Codex] Received 401 during getUsageLimits. Triggering background refresh...');
|
||||
|
||||
// 标记当前凭证为不健康
|
||||
const poolManager = getProviderPoolManager();
|
||||
if (poolManager && this.uuid) {
|
||||
logger.info(`[Codex] Marking credential ${this.uuid} as needs refresh. Reason: 401 Unauthorized in getUsageLimits`);
|
||||
poolManager.markProviderNeedRefresh(MODEL_PROVIDER.CODEX_API, {
|
||||
uuid: this.uuid
|
||||
});
|
||||
error.credentialMarkedUnhealthy = true;
|
||||
}
|
||||
// 触发后台异步刷新
|
||||
this.triggerBackgroundRefresh();
|
||||
error.credentialMarkedUnhealthy = true;
|
||||
|
||||
// Mark error for credential switch without recording error count
|
||||
error.shouldSwitchCredential = true;
|
||||
|
|
|
|||
Loading…
Reference in a new issue