From 669ef05940cbec20eb112a42a69609442954f1d3 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 23 Oct 2024 13:13:53 +0100 Subject: [PATCH] fix(trace viewer): limit the number of contexts loaded in sw UI mode may load many traces, one for each test, in the same service worker. This change introduces an upper limit to the number of traces stored in sw. --- packages/trace-viewer/src/sw/main.ts | 31 ++++++++++++------- .../src/ui/embeddedWorkbenchLoader.tsx | 1 + .../src/ui/recorder/modelContext.tsx | 1 + .../trace-viewer/src/ui/uiModeTraceView.tsx | 1 + .../trace-viewer/src/ui/workbenchLoader.tsx | 1 + 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/trace-viewer/src/sw/main.ts b/packages/trace-viewer/src/sw/main.ts index 6773b9fb76..6fcb08daa7 100644 --- a/packages/trace-viewer/src/sw/main.ts +++ b/packages/trace-viewer/src/sw/main.ts @@ -36,16 +36,16 @@ const scopePath = new URL(self.registration.scope).pathname; const loadedTraces = new Map(); -const clientIdToTraceUrls = new Map>(); +const clientIdToTraceUrls = new Map }>(); -async function loadTrace(traceUrl: string, traceFileName: string | null, clientId: string, progress: (done: number, total: number) => undefined): Promise { +async function loadTrace(traceUrl: string, traceFileName: string | null, clientId: string, limit: number | undefined, progress: (done: number, total: number) => undefined): Promise { await gc(); - let set = clientIdToTraceUrls.get(clientId); - if (!set) { - set = new Set(); - clientIdToTraceUrls.set(clientId, set); + let data = clientIdToTraceUrls.get(clientId); + if (!data) { + data = { limit, traceUrls: new Set() }; + clientIdToTraceUrls.set(clientId, data); } - set.add(traceUrl); + data.traceUrls.add(traceUrl); const traceModel = new TraceModel(); try { @@ -97,7 +97,8 @@ async function doFetch(event: FetchEvent): Promise { if (relativePath === '/contexts') { try { - const traceModel = await loadTrace(traceUrl!, url.searchParams.get('traceFileName'), event.clientId, (done: number, total: number) => { + const limit = url.searchParams.has('limit') ? +url.searchParams.get('limit')! : undefined; + const traceModel = await loadTrace(traceUrl!, url.searchParams.get('traceFileName'), event.clientId, limit, (done: number, total: number) => { client.postMessage({ method: 'progress', params: { done, total } }); }); return new Response(JSON.stringify(traceModel!.contextEntries), { @@ -179,12 +180,18 @@ async function gc() { const clients = await self.clients.matchAll(); const usedTraces = new Set(); - for (const [clientId, traceUrls] of clientIdToTraceUrls) { + for (const [clientId, data] of clientIdToTraceUrls) { // @ts-ignore - if (!clients.find(c => c.id === clientId)) + if (!clients.find(c => c.id === clientId)) { clientIdToTraceUrls.delete(clientId); - else - traceUrls.forEach(url => usedTraces.add(url)); + continue; + } + if (data.limit !== undefined) { + const ordered = [...data.traceUrls]; + // Leave the newest requested traces. + data.traceUrls = new Set(ordered.slice(ordered.length - data.limit)); + } + data.traceUrls.forEach(url => usedTraces.add(url)); } for (const traceUrl of loadedTraces.keys()) { diff --git a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx b/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx index 3500b93b1f..b398897975 100644 --- a/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx +++ b/packages/trace-viewer/src/ui/embeddedWorkbenchLoader.tsx @@ -65,6 +65,7 @@ export const EmbeddedWorkbenchLoader: React.FunctionComponent = () => { const url = traceURLs[i]; const params = new URLSearchParams(); params.set('trace', url); + params.set('limit', String(traceURLs.length)); const response = await fetch(`contexts?${params.toString()}`); if (!response.ok) { setProcessingErrorMessage((await response.json()).error); diff --git a/packages/trace-viewer/src/ui/recorder/modelContext.tsx b/packages/trace-viewer/src/ui/recorder/modelContext.tsx index 9db52e1964..98f450361b 100644 --- a/packages/trace-viewer/src/ui/recorder/modelContext.tsx +++ b/packages/trace-viewer/src/ui/recorder/modelContext.tsx @@ -58,6 +58,7 @@ export const ModelProvider: React.FunctionComponent { const params = new URLSearchParams(); params.set('trace', url); + params.set('limit', '1'); const response = await fetch(`contexts?${params.toString()}`); const contextEntries = await response.json() as ContextEntry[]; diff --git a/packages/trace-viewer/src/ui/uiModeTraceView.tsx b/packages/trace-viewer/src/ui/uiModeTraceView.tsx index ed63a2adab..cf35d89007 100644 --- a/packages/trace-viewer/src/ui/uiModeTraceView.tsx +++ b/packages/trace-viewer/src/ui/uiModeTraceView.tsx @@ -111,6 +111,7 @@ const outputDirForTestCase = (testCase: reporterTypes.TestCase): string | undefi 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()}`); const contextEntries = await response.json() as ContextEntry[]; return new MultiTraceModel(contextEntries); diff --git a/packages/trace-viewer/src/ui/workbenchLoader.tsx b/packages/trace-viewer/src/ui/workbenchLoader.tsx index 19793d4b57..72c02a4f6c 100644 --- a/packages/trace-viewer/src/ui/workbenchLoader.tsx +++ b/packages/trace-viewer/src/ui/workbenchLoader.tsx @@ -131,6 +131,7 @@ export const WorkbenchLoader: React.FunctionComponent<{ params.set('trace', url); if (uploadedTraceNames.length) params.set('traceFileName', uploadedTraceNames[i]); + params.set('limit', String(traceURLs.length)); const response = await fetch(`contexts?${params.toString()}`); if (!response.ok) { if (!isServer)