Skip to content

Commit 08cbb3d

Browse files
committed
Merge PR #291: refactor: extract account manager cache entry wrapper
2 parents 2193df4 + 9c401b5 commit 08cbb3d

22 files changed

Lines changed: 918 additions & 373 deletions

index.ts

Lines changed: 102 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -193,30 +193,35 @@ import {
193193
} from "./lib/runtime/account-check-helpers.js";
194194
import { runRuntimeAccountCheck } from "./lib/runtime/account-check.js";
195195
import { createAccountCheckWorkingState } from "./lib/runtime/account-check-types.js";
196+
import {
197+
invalidateRuntimeAccountManagerCache,
198+
reloadRuntimeAccountManager,
199+
} from "./lib/runtime/account-manager-cache.js";
196200
import {
197201
type TokenSuccessWithAccount as AccountPoolTokenSuccessWithAccount,
198202
persistAccountPoolResults,
199203
} from "./lib/runtime/account-pool.js";
200-
import { handleAccountSelectEvent } from "./lib/runtime/account-select-event.js";
201204
import { resolveAccountSelection } from "./lib/runtime/account-selection.js";
202205
import {
203206
formatRateLimitEntry,
204207
getRateLimitResetTimeForFamily,
205208
resolveActiveIndex,
206209
} from "./lib/runtime/account-status.js";
207-
import {
208-
invalidateRuntimeAccountManagerCache,
209-
reloadRuntimeAccountManager,
210-
} from "./lib/runtime/account-manager-cache.js";
211210
import {
212211
createPersistAccounts,
213212
runRuntimeOAuthFlow,
214213
} from "./lib/runtime/auth-facade.js";
214+
import { applyAccountStorageScopeEntry } from "./lib/runtime/account-storage-scope-entry.js";
215215
import { runBrowserOAuthFlow } from "./lib/runtime/browser-oauth-flow.js";
216+
import { handleRuntimeEvent } from "./lib/runtime/event-handler.js";
216217
import { hydrateRuntimeEmails } from "./lib/runtime/hydrate-emails.js";
217218
import { buildLoginMenuAccounts } from "./lib/runtime/login-menu-accounts.js";
219+
import { ensureLiveAccountSyncEntry } from "./lib/runtime/live-sync-entry.js";
220+
import { applyLoaderRuntimeSetup } from "./lib/runtime/loader-setup.js";
218221
import { buildManualOAuthFlow } from "./lib/runtime/manual-oauth-flow.js";
219-
import { applyRuntimePreemptiveQuotaSettings } from "./lib/runtime/preemptive-quota.js";
222+
import {
223+
applyPreemptiveQuotaSettingsFromConfig,
224+
} from "./lib/runtime/quota-settings.js";
220225
import {
221226
ensureLiveAccountSyncState,
222227
ensureRefreshGuardianState,
@@ -418,16 +423,44 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
418423
authFallback,
419424
});
420425

426+
const reloadAccountManagerFromDisk = async (
427+
authFallback?: OAuthAuthDetails,
428+
): Promise<AccountManager> =>
429+
reloadRuntimeAccountManager<AccountManager>(
430+
makeReloadAccountManagerDeps(authFallback),
431+
);
432+
433+
const applyAccountStorageScope = (
434+
pluginConfig: ReturnType<typeof loadPluginConfig>,
435+
): void =>
436+
applyAccountStorageScopeEntry({
437+
pluginConfig,
438+
getPerProjectAccounts,
439+
getStorageBackupEnabled,
440+
setStorageBackupEnabled,
441+
isCodexCliSyncEnabled,
442+
getWarningShown: () => perProjectStorageWarningShown,
443+
setWarningShown: (shown) => {
444+
perProjectStorageWarningShown = shown;
445+
},
446+
logWarn,
447+
pluginName: PLUGIN_NAME,
448+
setStoragePath,
449+
cwd: () => process.cwd(),
450+
applyAccountStorageScopeFromConfig,
451+
});
452+
421453
const ensureLiveAccountSync = async (
422454
pluginConfig: ReturnType<typeof loadPluginConfig>,
423455
authFallback?: OAuthAuthDetails,
424456
): Promise<void> => {
425-
const next = await ensureLiveAccountSyncState({
426-
enabled: getLiveAccountSync(pluginConfig),
427-
targetPath: getStoragePath(),
457+
const next = await ensureLiveAccountSyncEntry({
458+
pluginConfig,
459+
authFallback,
428460
currentSync: liveAccountSync,
429461
currentPath: liveAccountSyncPath,
430-
authFallback,
462+
getLiveAccountSync,
463+
getStoragePath,
431464
createSync: (oauthFallback) =>
432465
new LiveAccountSync(
433466
async () => {
@@ -443,6 +476,7 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
443476
registerCleanup,
444477
logWarn,
445478
pluginName: PLUGIN_NAME,
479+
ensureLiveAccountSyncState,
446480
});
447481
liveAccountSync = next.liveAccountSync;
448482
liveAccountSyncPath = next.liveAccountSyncPath;
@@ -471,38 +505,59 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
471505
next.refreshGuardianCleanupRegistered;
472506
};
473507

508+
const ensureSessionAffinity = (
509+
pluginConfig: ReturnType<typeof loadPluginConfig>,
510+
): void => {
511+
const next = ensureSessionAffinityState({
512+
enabled:
513+
getSessionAffinity(pluginConfig) ||
514+
getResponseContinuation(pluginConfig),
515+
ttlMs: getSessionAffinityTtlMs(pluginConfig),
516+
maxEntries: getSessionAffinityMaxEntries(pluginConfig),
517+
currentStore: sessionAffinityStore,
518+
currentConfigKey: sessionAffinityConfigKey,
519+
createStore: ({ ttlMs, maxEntries }) =>
520+
new SessionAffinityStore({ ttlMs, maxEntries }),
521+
});
522+
sessionAffinityStore = next.sessionAffinityStore;
523+
sessionAffinityConfigKey = next.sessionAffinityConfigKey;
524+
};
525+
526+
const applyPreemptiveQuotaSettings = (
527+
pluginConfig: ReturnType<typeof loadPluginConfig>,
528+
): void =>
529+
applyPreemptiveQuotaSettingsFromConfig(pluginConfig, {
530+
configure: (options) => preemptiveQuotaScheduler.configure(options),
531+
getPreemptiveQuotaEnabled,
532+
getPreemptiveQuotaRemainingPercent5h,
533+
getPreemptiveQuotaRemainingPercent7d,
534+
getPreemptiveQuotaMaxDeferralMs,
535+
});
536+
474537
// Event handler for session recovery and account selection
475538
const eventHandler = async (input: {
476539
event: { type: string; properties?: unknown };
477-
}) => {
478-
try {
479-
const handled = await handleAccountSelectEvent({
480-
event: input.event,
481-
providerId: PROVIDER_ID,
482-
loadAccounts,
483-
saveAccounts,
484-
modelFamilies: MODEL_FAMILIES,
485-
getCachedAccountManager: () => cachedAccountManager,
486-
reloadAccountManagerFromDisk: async () => {
487-
await reloadRuntimeAccountManager<AccountManager>(
488-
makeReloadAccountManagerDeps(),
489-
);
490-
},
491-
setLastCodexCliActiveSyncIndex: (index) => {
492-
lastCodexCliActiveSyncIndex = index;
493-
},
494-
showToast: (message, variant) =>
495-
showRuntimeToast(client, message, variant),
496-
});
497-
if (handled) {
498-
return;
499-
}
500-
} catch (error) {
501-
logDebug(
502-
`[${PLUGIN_NAME}] Event handler error: ${error instanceof Error ? error.message : String(error)}`,
503-
);
504-
}
505-
};
540+
}) =>
541+
handleRuntimeEvent({
542+
input,
543+
providerId: PROVIDER_ID,
544+
modelFamilies: MODEL_FAMILIES,
545+
loadAccounts,
546+
saveAccounts,
547+
hasCachedAccountManager: () => !!cachedAccountManager,
548+
syncCodexCliActiveSelectionForIndex: async (index) => {
549+
if (!cachedAccountManager) return;
550+
await cachedAccountManager.syncCodexCliActiveSelectionForIndex(index);
551+
},
552+
setLastCodexCliActiveSyncIndex: (index) => {
553+
lastCodexCliActiveSyncIndex = index;
554+
},
555+
reloadAccountManagerFromDisk: () => reloadAccountManagerFromDisk(),
556+
showToast: (message, variant) =>
557+
showRuntimeToast(client, message, variant),
558+
logDebug,
559+
pluginName: PLUGIN_NAME,
560+
});
506561

507562
// Initialize runtime UI settings once on plugin load; auth/tools refresh this dynamically.
508563
applyUiRuntimeFromConfig(loadPluginConfig(), setUiRuntimeOptions);
@@ -528,43 +583,14 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
528583
async loader(getAuth: () => Promise<Auth>, provider: unknown) {
529584
const auth = await getAuth();
530585
const pluginConfig = loadPluginConfig();
531-
applyUiRuntimeFromConfig(pluginConfig, setUiRuntimeOptions);
532-
applyAccountStorageScopeFromConfig(pluginConfig, {
533-
getPerProjectAccounts,
534-
getStorageBackupEnabled,
535-
setStorageBackupEnabled,
536-
isCodexCliSyncEnabled,
537-
getWarningShown: () => perProjectStorageWarningShown,
538-
setWarningShown: (shown) => {
539-
perProjectStorageWarningShown = shown;
540-
},
541-
logWarn,
542-
pluginName: PLUGIN_NAME,
543-
setStoragePath,
544-
cwd: () => process.cwd(),
545-
});
546-
{
547-
const next = ensureSessionAffinityState({
548-
enabled:
549-
getSessionAffinity(pluginConfig) ||
550-
getResponseContinuation(pluginConfig),
551-
ttlMs: getSessionAffinityTtlMs(pluginConfig),
552-
maxEntries: getSessionAffinityMaxEntries(pluginConfig),
553-
currentStore: sessionAffinityStore,
554-
currentConfigKey: sessionAffinityConfigKey,
555-
createStore: ({ ttlMs, maxEntries }) =>
556-
new SessionAffinityStore({ ttlMs, maxEntries }),
557-
});
558-
sessionAffinityStore = next.sessionAffinityStore;
559-
sessionAffinityConfigKey = next.sessionAffinityConfigKey;
560-
}
561-
ensureRefreshGuardian(pluginConfig);
562-
applyRuntimePreemptiveQuotaSettings(pluginConfig, {
563-
configure: (options) => preemptiveQuotaScheduler.configure(options),
564-
getPreemptiveQuotaEnabled,
565-
getPreemptiveQuotaRemainingPercent5h,
566-
getPreemptiveQuotaRemainingPercent7d,
567-
getPreemptiveQuotaMaxDeferralMs,
586+
applyLoaderRuntimeSetup({
587+
pluginConfig,
588+
applyUiRuntimeFromConfig: (config) =>
589+
applyUiRuntimeFromConfig(config, setUiRuntimeOptions),
590+
applyAccountStorageScope,
591+
ensureSessionAffinity,
592+
ensureRefreshGuardian,
593+
applyPreemptiveQuotaSettings,
568594
});
569595

570596
// Only handle OAuth auth type, skip API key auth
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { OAuthAuthDetails } from "../types.js";
2+
3+
export function invalidateAccountManagerCacheEntry<TManager>(params: {
4+
invalidateAccountManagerCacheState: () => {
5+
cachedAccountManager: null;
6+
accountManagerPromise: null;
7+
};
8+
setCachedAccountManager: (manager: TManager | null) => void;
9+
setAccountManagerPromise: (promise: Promise<TManager> | null) => void;
10+
}): void {
11+
const next = params.invalidateAccountManagerCacheState();
12+
params.setCachedAccountManager(next.cachedAccountManager);
13+
params.setAccountManagerPromise(next.accountManagerPromise);
14+
}
15+
16+
export async function reloadAccountManagerFromDiskEntry<TManager>(params: {
17+
authFallback?: OAuthAuthDetails;
18+
currentReloadInFlight: Promise<TManager> | null;
19+
reloadAccountManagerFromDiskState: (args: {
20+
currentReloadInFlight: Promise<TManager> | null;
21+
loadFromDisk: (authFallback?: OAuthAuthDetails) => Promise<TManager>;
22+
authFallback?: OAuthAuthDetails;
23+
onLoaded: (manager: TManager) => void;
24+
onSettled: () => void;
25+
}) => Promise<TManager>;
26+
loadFromDisk: (authFallback?: OAuthAuthDetails) => Promise<TManager>;
27+
onLoaded: (manager: TManager) => void;
28+
onSettled: () => void;
29+
setReloadInFlight: (promise: Promise<TManager>) => void;
30+
}): Promise<TManager> {
31+
const inFlight = params.reloadAccountManagerFromDiskState({
32+
currentReloadInFlight: params.currentReloadInFlight,
33+
loadFromDisk: params.loadFromDisk,
34+
authFallback: params.authFallback,
35+
onLoaded: params.onLoaded,
36+
onSettled: params.onSettled,
37+
});
38+
params.setReloadInFlight(inFlight);
39+
return inFlight;
40+
}

lib/runtime/account-manager-cache.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ export function invalidateRuntimeAccountManagerCache(deps: {
88
deps.setAccountManagerPromise(null);
99
}
1010

11+
export function invalidateAccountManagerCacheState(): {
12+
cachedAccountManager: null;
13+
accountManagerPromise: null;
14+
} {
15+
return {
16+
cachedAccountManager: null,
17+
accountManagerPromise: null,
18+
};
19+
}
20+
1121
export function reloadRuntimeAccountManager<TAccountManager>(deps: {
1222
currentReloadInFlight: Promise<TAccountManager> | null;
1323
loadFromDisk: (authFallback?: OAuthAuthDetails) => Promise<TAccountManager>;
@@ -34,3 +44,27 @@ export function reloadRuntimeAccountManager<TAccountManager>(deps: {
3444
deps.setReloadInFlight(reloadInFlight);
3545
return reloadInFlight;
3646
}
47+
48+
export async function reloadAccountManagerFromDiskState<TManager>(params: {
49+
currentReloadInFlight: Promise<TManager> | null;
50+
loadFromDisk: (authFallback?: OAuthAuthDetails) => Promise<TManager>;
51+
authFallback?: OAuthAuthDetails;
52+
onLoaded: (manager: TManager) => void;
53+
onSettled: () => void;
54+
}): Promise<TManager> {
55+
if (params.currentReloadInFlight) {
56+
return params.currentReloadInFlight;
57+
}
58+
59+
const inFlight = (async () => {
60+
const reloaded = await params.loadFromDisk(params.authFallback);
61+
params.onLoaded(reloaded);
62+
return reloaded;
63+
})();
64+
65+
try {
66+
return await inFlight;
67+
} finally {
68+
params.onSettled();
69+
}
70+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
export function applyAccountStorageScopeEntry(params: {
2+
pluginConfig: ReturnType<typeof import("../config.js").loadPluginConfig>;
3+
getPerProjectAccounts: (
4+
config: ReturnType<typeof import("../config.js").loadPluginConfig>,
5+
) => boolean;
6+
getStorageBackupEnabled: (
7+
config: ReturnType<typeof import("../config.js").loadPluginConfig>,
8+
) => boolean;
9+
setStorageBackupEnabled: (enabled: boolean) => void;
10+
isCodexCliSyncEnabled: () => boolean;
11+
getWarningShown: () => boolean;
12+
setWarningShown: (shown: boolean) => void;
13+
logWarn: (message: string) => void;
14+
pluginName: string;
15+
setStoragePath: (path: string | null) => void;
16+
cwd: () => string;
17+
applyAccountStorageScopeFromConfig: (
18+
pluginConfig: ReturnType<typeof import("../config.js").loadPluginConfig>,
19+
deps: {
20+
getPerProjectAccounts: (
21+
config: ReturnType<typeof import("../config.js").loadPluginConfig>,
22+
) => boolean;
23+
getStorageBackupEnabled: (
24+
config: ReturnType<typeof import("../config.js").loadPluginConfig>,
25+
) => boolean;
26+
setStorageBackupEnabled: (enabled: boolean) => void;
27+
isCodexCliSyncEnabled: () => boolean;
28+
getWarningShown: () => boolean;
29+
setWarningShown: (shown: boolean) => void;
30+
logWarn: (message: string) => void;
31+
pluginName: string;
32+
setStoragePath: (path: string | null) => void;
33+
cwd: () => string;
34+
},
35+
) => void;
36+
}): void {
37+
params.applyAccountStorageScopeFromConfig(params.pluginConfig, {
38+
getPerProjectAccounts: params.getPerProjectAccounts,
39+
getStorageBackupEnabled: params.getStorageBackupEnabled,
40+
setStorageBackupEnabled: params.setStorageBackupEnabled,
41+
isCodexCliSyncEnabled: params.isCodexCliSyncEnabled,
42+
getWarningShown: params.getWarningShown,
43+
setWarningShown: params.setWarningShown,
44+
logWarn: params.logWarn,
45+
pluginName: params.pluginName,
46+
setStoragePath: params.setStoragePath,
47+
cwd: params.cwd,
48+
});
49+
}

0 commit comments

Comments
 (0)