diff --git a/src/routes/plans/[id]/+page.svelte b/src/routes/plans/[id]/+page.svelte index 7479fef318..c9669cab1c 100644 --- a/src/routes/plans/[id]/+page.svelte +++ b/src/routes/plans/[id]/+page.svelte @@ -73,6 +73,7 @@ import { enableSimulation, externalResources, + fetchingResources, resetSimulationStores, resourceTypes, resources, @@ -152,6 +153,8 @@ let simulationExtent: string | null; let selectedSimulationStatus: string | null; let windowWidth = 0; + let simulationDataAbortController: AbortController; + let resourcesExternalAbortController: AbortController; $: activityErrorCounts = $activityErrorRollups.reduce( (prevCounts, activityErrorRollup) => { @@ -275,8 +278,16 @@ } $: if ($plan) { + resourcesExternalAbortController?.abort(); + resourcesExternalAbortController = new AbortController(); effects - .getResourcesExternal($plan.id, $simulationDatasetId ?? null, $plan.start_time, data.user) + .getResourcesExternal( + $plan.id, + $simulationDatasetId ?? null, + $plan.start_time, + data.user, + resourcesExternalAbortController.signal, + ) .then(newResources => ($externalResources = newResources)); } @@ -285,16 +296,25 @@ selectActivity(null, null); } - $: if ($plan && $simulationDataset !== undefined) { - if ($simulationDataset !== null && $simulationDatasetId !== -1) { - const datasetId = $simulationDataset.dataset_id; - const startTimeYmd = $simulationDataset?.simulation_start_time ?? $plan.start_time; - effects.getResources(datasetId, startTimeYmd, data.user).then(newResources => ($resources = newResources)); - effects.getSpans(datasetId, data.user).then(newSpans => ($spans = newSpans)); - } else { - $resources = []; - $spans = []; - } + $: if ( + $plan && + $simulationDatasetId !== -1 && + $simulationDataset?.id === $simulationDatasetId && + getSimulationStatus($simulationDataset) === Status.Complete + ) { + const datasetId = $simulationDatasetId; + const startTimeYmd = $simulationDataset?.simulation_start_time ?? $plan.start_time; + simulationDataAbortController?.abort(); + simulationDataAbortController = new AbortController(); + effects + .getResources(datasetId, startTimeYmd, data.user, simulationDataAbortController.signal) + .then(newResources => ($resources = newResources)); + effects.getSpans(datasetId, data.user, simulationDataAbortController.signal).then(newSpans => ($spans = newSpans)); + } else { + simulationDataAbortController?.abort(); + fetchingResources.set(false); + $resources = []; + $spans = []; } $: { diff --git a/src/stores/simulation.ts b/src/stores/simulation.ts index f4d0a96c8d..4a1915d7d5 100644 --- a/src/stores/simulation.ts +++ b/src/stores/simulation.ts @@ -30,6 +30,8 @@ export const resources: Writable = writable([]); export const fetchingResources: Writable = writable(false); +export const fetchingResourcesExternal: Writable = writable(false); + export const resourceTypes: Writable = writable([]); export const spans: Writable = writable([]); diff --git a/src/utilities/effects.ts b/src/utilities/effects.ts index 3d5040f0bc..49718859b2 100644 --- a/src/utilities/effects.ts +++ b/src/utilities/effects.ts @@ -17,7 +17,12 @@ import { import { createModelError, createPlanError, creatingModel, creatingPlan, models } from '../stores/plan'; import { schedulingStatus, selectedSpecId } from '../stores/scheduling'; import { commandDictionaries } from '../stores/sequencing'; -import { fetchingResources, selectedSpanId, simulationDatasetId } from '../stores/simulation'; +import { + fetchingResources, + fetchingResourcesExternal, + selectedSpanId, + simulationDatasetId, +} from '../stores/simulation'; import { createTagError } from '../stores/tags'; import { applyViewUpdate, view, viewUpdateTimeline } from '../stores/views'; import type { @@ -2848,17 +2853,25 @@ const effects = { } }, - async getResources(datasetId: number, startTimeYmd: string, user: User | null): Promise { + async getResources( + datasetId: number, + startTimeYmd: string, + user: User | null, + signal: AbortSignal | undefined = undefined, + ): Promise { try { fetchingResources.set(true); - const data = await reqHasura(gql.GET_PROFILES, { datasetId }, user); + const data = await reqHasura(gql.GET_PROFILES, { datasetId }, user, signal); const { profile: profiles } = data; const sampledProfiles = sampleProfiles(profiles, startTimeYmd); fetchingResources.set(false); return sampledProfiles; } catch (e) { - catchError(e as Error); - fetchingResources.set(false); + const error = e as Error; + if (error.name !== 'AbortError') { + catchError(error); + fetchingResources.set(false); + } return []; } }, @@ -2868,8 +2881,10 @@ const effects = { simulationDatasetId: number | null, startTimeYmd: string, user: User | null, + signal: AbortSignal | undefined = undefined, ): Promise { try { + fetchingResourcesExternal.set(true); const data = await reqHasura( gql.GET_PROFILES_EXTERNAL, { @@ -2882,6 +2897,7 @@ const effects = { : { _eq: simulationDatasetId }, }, user, + signal, ); const { plan_dataset: plan_datasets } = data; if (plan_datasets != null) { @@ -2894,13 +2910,17 @@ const effects = { const sampledResources: Resource[] = sampleProfiles(profiles, startTimeYmd, offset_from_plan_start); resources = [...resources, ...sampledResources]; } - + fetchingResourcesExternal.set(false); return resources; } else { throw Error('Unable to get external resources'); } } catch (e) { - catchError(e as Error); + const error = e as Error; + if (error.name !== 'AbortError') { + catchError(error); + fetchingResourcesExternal.set(false); + } return []; } }, @@ -3004,9 +3024,9 @@ const effects = { } }, - async getSpans(datasetId: number, user: User | null): Promise { + async getSpans(datasetId: number, user: User | null, signal: AbortSignal | undefined = undefined): Promise { try { - const data = await reqHasura(gql.GET_SPANS, { datasetId }, user); + const data = await reqHasura(gql.GET_SPANS, { datasetId }, user, signal); const { span: spans } = data; if (spans != null) { return spans;