mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-08-29 00:41:25 +08:00
fix(auth-files): invalidate quota cache on mutations
This commit is contained in:
@@ -29,6 +29,7 @@ import { OAuthModelAliasCard } from '@/features/authFiles/components/OAuthModelA
|
||||
import { ProviderTabs } from '@/features/authFiles/components/ProviderTabs';
|
||||
import { VaultHeader } from '@/features/authFiles/components/VaultHeader';
|
||||
import { VaultPulse } from '@/features/authFiles/components/VaultPulse';
|
||||
import { invalidateAuthFileDerivedCaches } from '@/features/authFiles/cacheInvalidation';
|
||||
import { useAuthFilesData } from '@/features/authFiles/hooks/useAuthFilesData';
|
||||
import { useAuthFilesModels } from '@/features/authFiles/hooks/useAuthFilesModels';
|
||||
import { useAuthFilesOauth } from '@/features/authFiles/hooks/useAuthFilesOauth';
|
||||
@@ -110,6 +111,11 @@ export function AuthFilesPage() {
|
||||
invalidateModels,
|
||||
} = useAuthFilesModels();
|
||||
|
||||
const invalidateDerivedCaches = useCallback(
|
||||
(names?: string[]) => invalidateAuthFileDerivedCaches(invalidateModels, names),
|
||||
[invalidateModels]
|
||||
);
|
||||
|
||||
const {
|
||||
files,
|
||||
selectedFiles,
|
||||
@@ -139,7 +145,7 @@ export function AuthFilesPage() {
|
||||
batchDownload,
|
||||
batchSetStatus,
|
||||
batchDelete,
|
||||
} = useAuthFilesData({ onFilesMutated: invalidateModels });
|
||||
} = useAuthFilesData({ onFilesMutated: invalidateDerivedCaches });
|
||||
|
||||
const statusBarCache = useAuthFilesStatusBarCache(files);
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { useQuotaStore } from '@/stores/useQuotaStore';
|
||||
|
||||
type ModelsInvalidator = (names?: string[]) => void;
|
||||
|
||||
/** Invalidate every cache whose contents depend on an auth file's credentials. */
|
||||
export const invalidateAuthFileDerivedCaches = (
|
||||
invalidateModels: ModelsInvalidator,
|
||||
names?: string[]
|
||||
): void => {
|
||||
invalidateModels(names);
|
||||
useQuotaStore.getState().clearQuotaCache();
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
import { beforeEach, describe, expect, test } from 'bun:test';
|
||||
import { invalidateAuthFileDerivedCaches } from '../src/features/authFiles/cacheInvalidation';
|
||||
import {
|
||||
captureQuotaCacheGeneration,
|
||||
commitIfQuotaCacheCurrent,
|
||||
@@ -35,4 +36,35 @@ describe('quota cache session isolation', () => {
|
||||
).toBe(true);
|
||||
expect(committed).toBe(true);
|
||||
});
|
||||
|
||||
test('clears same-name quota and rejects an in-flight commit after auth mutation', () => {
|
||||
const fileName = 'shared-codex.json';
|
||||
useQuotaStore.getState().setCodexQuota({
|
||||
[fileName]: {
|
||||
status: 'success',
|
||||
windows: [],
|
||||
planType: 'account-a',
|
||||
},
|
||||
});
|
||||
const accountARequest = captureQuotaCacheGeneration();
|
||||
let invalidatedNames: string[] | undefined;
|
||||
|
||||
invalidateAuthFileDerivedCaches(
|
||||
(names) => {
|
||||
invalidatedNames = names;
|
||||
},
|
||||
[fileName]
|
||||
);
|
||||
|
||||
expect(invalidatedNames).toEqual([fileName]);
|
||||
expect(useQuotaStore.getState().codexQuota[fileName]).toBeUndefined();
|
||||
|
||||
let committed = false;
|
||||
expect(
|
||||
commitIfQuotaCacheCurrent(accountARequest, () => {
|
||||
committed = true;
|
||||
})
|
||||
).toBe(false);
|
||||
expect(committed).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user