fix(ui): recover from corrupt chunk reload markers (#1230)
* fix(ui): recover from corrupt chunk reload markers * test(ui): clarify chunk recovery assertions --------- Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
This commit is contained in:
committed by
GitHub
co-authored by
Isaac Sanchez
parent
eeabc304bd
commit
416a11dcce
@@ -0,0 +1,51 @@
|
||||
import { describe, expect, test } from 'bun:test';
|
||||
|
||||
import { importWithChunkRecovery } from './chunkLoadRecovery';
|
||||
|
||||
describe('importWithChunkRecovery', () => {
|
||||
test('schedules recovery reload when stored reload marker is corrupt', async () => {
|
||||
const globalWithWindow = globalThis as unknown as { window?: unknown };
|
||||
const previousWindow = globalWithWindow.window;
|
||||
let storedMarker: string | null = null;
|
||||
let reloadCount = 0;
|
||||
|
||||
globalWithWindow.window = {
|
||||
sessionStorage: {
|
||||
getItem: () => '{not json',
|
||||
setItem: (_key: string, value: string) => {
|
||||
storedMarker = value;
|
||||
},
|
||||
},
|
||||
setTimeout: (callback: () => void) => {
|
||||
callback();
|
||||
return 0;
|
||||
},
|
||||
location: {
|
||||
reload: () => {
|
||||
reloadCount += 1;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
let caught: unknown;
|
||||
try {
|
||||
await importWithChunkRecovery(async () => {
|
||||
throw new Error('Failed to fetch dynamically imported module');
|
||||
}, { retries: 0 });
|
||||
} catch (error) {
|
||||
caught = error;
|
||||
}
|
||||
|
||||
expect(caught).toBeInstanceOf(Error);
|
||||
expect(storedMarker).not.toBeNull();
|
||||
expect(reloadCount).toBe(1);
|
||||
} finally {
|
||||
if (previousWindow === undefined) {
|
||||
delete globalWithWindow.window;
|
||||
} else {
|
||||
globalWithWindow.window = previousWindow;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -46,13 +46,26 @@ function scheduleReloadOnce(error: unknown): void {
|
||||
const now = Date.now();
|
||||
const signature = reloadMarkerSignature(error);
|
||||
|
||||
let marker: { signature?: unknown; timestamp?: unknown } | null = null;
|
||||
try {
|
||||
const rawMarker = window.sessionStorage.getItem(RELOAD_STORAGE_KEY);
|
||||
const marker = rawMarker ? JSON.parse(rawMarker) as { signature?: unknown; timestamp?: unknown } : null;
|
||||
const markerTimestamp = typeof marker?.timestamp === 'number' ? marker.timestamp : 0;
|
||||
if (marker?.signature === signature && now - markerTimestamp < RELOAD_GUARD_MS) {
|
||||
return;
|
||||
if (rawMarker) {
|
||||
try {
|
||||
marker = JSON.parse(rawMarker) as { signature?: unknown; timestamp?: unknown };
|
||||
} catch {
|
||||
marker = null;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const markerTimestamp = typeof marker?.timestamp === 'number' ? marker.timestamp : 0;
|
||||
if (marker?.signature === signature && now - markerTimestamp < RELOAD_GUARD_MS) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
window.sessionStorage.setItem(RELOAD_STORAGE_KEY, JSON.stringify({ signature, timestamp: now }));
|
||||
} catch {
|
||||
return;
|
||||
|
||||
Vendored
+2
@@ -15,10 +15,12 @@ declare module "bun:test" {
|
||||
toBeGreaterThan(expected: number): void;
|
||||
toBeLessThan(expected: number): void;
|
||||
toHaveLength(expected: number): void;
|
||||
toBeInstanceOf(expected: unknown): void;
|
||||
not: {
|
||||
toEqual(expected: unknown): void;
|
||||
toBe(expected: unknown): void;
|
||||
toContain(expected: unknown): void;
|
||||
toBeNull(): void;
|
||||
};
|
||||
};
|
||||
export function beforeEach(fn: () => void | Promise<void>): void;
|
||||
|
||||
Reference in New Issue
Block a user