fix(auth): harden diagnostic cleanup races

This commit is contained in:
2026-08-17 18:41:40 +02:00
parent af16464e68
commit d12b629420
7 changed files with 387 additions and 36 deletions
+30 -16
View File
@@ -87,8 +87,37 @@ export function WorkspaceManager({
const operationEpochRef = useRef(0);
const diagnosticEpochRef = useRef(0);
const selectedIdRef = useRef(selectedId);
const wasOpenRef = useRef(open);
selectedIdRef.current = selectedId;
const clearGlobalMessages = () => {
setNotice(undefined);
setDiagnostics([]);
};
const clearDiagnosticMessages = () => {
diagnosticEpochRef.current += 1;
setValidationNotice(undefined);
setValidationDiagnostics([]);
setConnectionNotice(undefined);
setConnectionDiagnostics([]);
setAuthentication(undefined);
setBusyAction((current) => current === "validate" || current === "test" ? undefined : current);
};
const clearMessages = () => {
clearGlobalMessages();
clearDiagnosticMessages();
};
useEffect(() => () => { operationEpochRef.current += 1; }, []);
useEffect(() => {
if (wasOpenRef.current && !open) {
setSecretValues({});
clearMessages();
}
wasOpenRef.current = open;
}, [open]);
async function guardedQuery<T>(request: () => Promise<T>, targetId?: string): Promise<T> {
const guard = captureAuthOperation({
@@ -131,21 +160,6 @@ export function WorkspaceManager({
enabled: Boolean(open && selectedId),
});
const clearMessages = () => {
setNotice(undefined);
setDiagnostics([]);
setValidationNotice(undefined);
setValidationDiagnostics([]);
setConnectionNotice(undefined);
setConnectionDiagnostics([]);
setAuthentication(undefined);
};
const clearGlobalMessages = () => {
setNotice(undefined);
setDiagnostics([]);
};
const close = () => {
setSecretValues({});
clearMessages();
@@ -167,8 +181,8 @@ export function WorkspaceManager({
async function updateRepository() {
const guard = captureAuthOperation({ disposalEpoch: operationEpochRef.current });
if (!guard) return;
setBusyAction("repository");
clearMessages();
setBusyAction("repository");
try {
await pullWorkspaceRegistry();
if (!isAuthOperationCurrent(guard, { disposalEpoch: operationEpochRef.current })) return;