From d8725a3c16d6e25a87d1a763442df463e4712e0f Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Mon, 4 Nov 2024 15:58:41 +0100 Subject: [PATCH] chore(ui): handle trace not being available without exceptions --- packages/trace-viewer/src/sw/main.ts | 4 ++++ .../trace-viewer/src/sw/traceModelBackends.ts | 5 ++++- .../trace-viewer/src/ui/uiModeTraceView.tsx | 17 ++++++++++------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/trace-viewer/src/sw/main.ts b/packages/trace-viewer/src/sw/main.ts index 6fcb08daa7..9be352baf8 100644 --- a/packages/trace-viewer/src/sw/main.ts +++ b/packages/trace-viewer/src/sw/main.ts @@ -54,6 +54,8 @@ async function loadTrace(traceUrl: string, traceFileName: string | null, clientI const backend = traceUrl.endsWith('json') ? new FetchTraceModelBackend(traceUrl) : new ZipTraceModelBackend(traceUrl, fetchProgress); await traceModel.load(backend, unzipProgress); } catch (error: any) { + if (error?.message === 'trace not found') + throw error; // eslint-disable-next-line no-console console.error(error); if (error?.message?.includes('Cannot find .trace file') && await traceModel.hasEntry('index.html')) @@ -106,6 +108,8 @@ async function doFetch(event: FetchEvent): Promise { headers: { 'Content-Type': 'application/json' } }); } catch (error: any) { + if (error?.message === 'trace not found') + return new Response(null, { status: 404 }); return new Response(JSON.stringify({ error: error?.message }), { status: 500, headers: { 'Content-Type': 'application/json' } diff --git a/packages/trace-viewer/src/sw/traceModelBackends.ts b/packages/trace-viewer/src/sw/traceModelBackends.ts index 19c5fc2dee..b775485b6c 100644 --- a/packages/trace-viewer/src/sw/traceModelBackends.ts +++ b/packages/trace-viewer/src/sw/traceModelBackends.ts @@ -88,7 +88,10 @@ export class FetchTraceModelBackend implements TraceModelBackend { constructor(traceURL: string) { this._traceURL = traceURL; this._entriesPromise = fetch('/trace/file?path=' + encodeURIComponent(traceURL)).then(async response => { - const json = JSON.parse(await response.text()); + if (response.status === 404) + throw new Error(`trace not found`); + + const json = await response.json(); const entries = new Map(); for (const entry of json.entries) entries.set(entry.name, entry.path); diff --git a/packages/trace-viewer/src/ui/uiModeTraceView.tsx b/packages/trace-viewer/src/ui/uiModeTraceView.tsx index cf35d89007..95f115a8ce 100644 --- a/packages/trace-viewer/src/ui/uiModeTraceView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTraceView.tsx @@ -33,7 +33,6 @@ export const TraceView: React.FC<{ pathSeparator: string, }> = ({ item, rootDir, onOpenExternally, revealSource, pathSeparator }) => { const [model, setModel] = React.useState<{ model: MultiTraceModel, isLive: boolean } | undefined>(); - const [counter, setCounter] = React.useState(0); const pollTimer = React.useRef(null); const { outputDir } = React.useMemo(() => { @@ -54,7 +53,10 @@ export const TraceView: React.FC<{ // Test finished. const attachment = result && result.duration >= 0 && result.attachments.find(a => a.name === 'trace'); if (attachment && attachment.path) { - loadSingleTraceFile(attachment.path).then(model => setModel({ model, isLive: false })); + loadSingleTraceFile(attachment.path).then(model => { + if (model) + setModel({ model, isLive: false }); + }); return; } @@ -73,18 +75,17 @@ export const TraceView: React.FC<{ pollTimer.current = setTimeout(async () => { try { const model = await loadSingleTraceFile(traceLocation); - setModel({ model, isLive: true }); + if (model) + setModel({ model, isLive: true }); } catch { setModel(undefined); - } finally { - setCounter(counter + 1); } }, 500); return () => { if (pollTimer.current) clearTimeout(pollTimer.current); }; - }, [outputDir, item, setModel, counter, setCounter, pathSeparator]); + }, [outputDir, item, setModel, pathSeparator]); return { +async function loadSingleTraceFile(url: string): Promise { const params = new URLSearchParams(); params.set('trace', url); params.set('limit', '1'); const response = await fetch(`contexts?${params.toString()}`); + if (response.status === 404) + return; const contextEntries = await response.json() as ContextEntry[]; return new MultiTraceModel(contextEntries); }