diff --git a/public/app/features/scenes/scenes/variablesDemo.tsx b/public/app/features/scenes/scenes/variablesDemo.tsx index aae519e72b7..2e71cf55865 100644 --- a/public/app/features/scenes/scenes/variablesDemo.tsx +++ b/public/app/features/scenes/scenes/variablesDemo.tsx @@ -7,7 +7,6 @@ import { SceneFlexLayout } from '../components/layout/SceneFlexLayout'; import { SceneTimeRange } from '../core/SceneTimeRange'; import { VariableValueSelectors } from '../variables/components/VariableValueSelectors'; import { SceneVariableSet } from '../variables/sets/SceneVariableSet'; -import { ConstantVariable } from '../variables/variants/ConstantVariable'; import { CustomVariable } from '../variables/variants/CustomVariable'; import { DataSourceVariable } from '../variables/variants/DataSourceVariable'; import { TestVariable } from '../variables/variants/TestVariable'; @@ -45,37 +44,14 @@ export function getVariablesDemo(): Scene { text: '', options: [], }), - new ConstantVariable({ - name: 'constant', - value: 'slow', - }), new CustomVariable({ - name: 'Single Custom', + name: 'custom', query: 'A : 10,B : 20', }), - new CustomVariable({ - name: 'Multi Custom', - query: 'A : 10,B : 20', - isMulti: true, - }), new DataSourceVariable({ - name: 'DataSource', + name: 'ds', query: 'testdata', }), - new DataSourceVariable({ - name: 'DataSource', - query: 'prometheus', - }), - new DataSourceVariable({ - name: 'DataSource multi', - query: 'prometheus', - isMulti: true, - }), - new DataSourceVariable({ - name: 'Datasource w/ regex and using $constant', - query: 'prometheus', - regex: '.*$constant.*', - }), ], }), layout: new SceneFlexLayout({ diff --git a/public/app/features/scenes/variables/sets/SceneVariableSet.test.tsx b/public/app/features/scenes/variables/sets/SceneVariableSet.test.tsx index c5898267f9b..6c41b10ced9 100644 --- a/public/app/features/scenes/variables/sets/SceneVariableSet.test.tsx +++ b/public/app/features/scenes/variables/sets/SceneVariableSet.test.tsx @@ -134,4 +134,28 @@ describe('SceneVariableList', () => { }); }); }); + + describe('When activated with variables update at the same time', () => { + it('Should not start variables multiple times', async () => { + const A = new TestVariable({ name: 'A', query: 'A.*', value: '', text: '', options: [] }); + const B = new TestVariable({ name: 'B', query: 'B.*', value: '', text: '', options: [] }); + + const scene = new TestScene({ + $variables: new SceneVariableSet({ variables: [A, B] }), + }); + + scene.activate(); + + // Should start variables + expect(A.state.loading).toBe(true); + expect(B.state.loading).toBe(true); + expect(A.getValueOptionsCount).toBe(1); + + // Complete the second one + B.signalUpdateCompleted(); + + // When B complete should not start another instance of A + expect(A.getValueOptionsCount).toBe(1); + }); + }); }); diff --git a/public/app/features/scenes/variables/sets/SceneVariableSet.ts b/public/app/features/scenes/variables/sets/SceneVariableSet.ts index 58ad9bedf80..32388dc83c9 100644 --- a/public/app/features/scenes/variables/sets/SceneVariableSet.ts +++ b/public/app/features/scenes/variables/sets/SceneVariableSet.ts @@ -60,6 +60,11 @@ export class SceneVariableSet extends SceneObjectBase imp throw new Error('Variable added to variablesToUpdate but does not have validateAndUpdate'); } + // Ignore it if it's already started + if (this.updating.has(variable)) { + continue; + } + // Wait for variables that has dependencies that also needs updates if (this.hasDependendencyInUpdateQueue(variable)) { continue; diff --git a/public/app/features/scenes/variables/variants/TestVariable.tsx b/public/app/features/scenes/variables/variants/TestVariable.tsx index a9ad24ec298..10601be6e9e 100644 --- a/public/app/features/scenes/variables/variants/TestVariable.tsx +++ b/public/app/features/scenes/variables/variants/TestVariable.tsx @@ -23,6 +23,7 @@ export interface TestVariableState extends MultiValueVariableState { export class TestVariable extends MultiValueVariable { private completeUpdate = new Subject(); public isGettingValues = true; + public getValueOptionsCount = 0; protected _variableDependency = new VariableDependencyConfig(this, { statePaths: ['query'], @@ -42,10 +43,12 @@ export class TestVariable extends MultiValueVariable { public getValueOptions(args: VariableGetOptionsArgs): Observable { const { delayMs } = this.state; + this.getValueOptionsCount += 1; + return new Observable((observer) => { this.setState({ loading: true }); - this.completeUpdate.subscribe({ + const sub = this.completeUpdate.subscribe({ next: () => { observer.next(this.issueQuery()); }, @@ -60,6 +63,7 @@ export class TestVariable extends MultiValueVariable { this.isGettingValues = true; return () => { + sub.unsubscribe(); clearTimeout(timeout); this.isGettingValues = false; };