[eric] boot: bootstrap fetches retry until the backend answers and heal on focus, so a lost boot race stops bricking first paint

This commit is contained in:
ciregenz
2026-08-08 09:34:13 -07:00
parent 5c0d6d52b6
commit d60a99ddd1
5 changed files with 45 additions and 2 deletions
+6 -1
View File
@@ -48,7 +48,12 @@ export async function refreshAuthToken(): Promise<string> {
/** Resolve auth token once; concurrent callers share the same promise. */
export function ensureAuthToken(): Promise<string> {
if (_authTokenPromise) return _authTokenPromise;
_authTokenPromise = refreshAuthToken();
_authTokenPromise = refreshAuthToken().then((tok) => {
// A boot race can resolve EMPTY (backend hadn't written the token file yet); memoizing that
// left the renderer auth-dead until a manual reload (ENG-207). Empty = not an answer; retry.
if (!tok) _authTokenPromise = null;
return tok;
});
return _authTokenPromise;
}
+7
View File
@@ -21,11 +21,13 @@ export interface ModelOption {
interface ModelsState {
byProvider: Record<string, ModelOption[]>;
loaded: boolean;
failed: boolean;
}
const initialState: ModelsState = {
byProvider: {},
loaded: false,
failed: false,
};
export const fetchModels = createAsyncThunk('models/fetchModels', async () => {
@@ -49,6 +51,11 @@ const modelsSlice = createSlice({
.addCase(fetchModels.rejected, (state) => {
// Mark loaded even on failure so callers fall back to hardcoded options.
state.loaded = true;
// ...but remember it FAILED: a boot-race miss used to read as "loaded with no models" and lit the red banner on a fully configured install (ENG-207).
state.failed = true;
})
.addCase(fetchModels.pending, (state) => {
state.failed = false;
});
},
});