mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Scene: Fixes infinite update loop (#59306)
* Scene: Fixes infinite update loop * fixed lint issue
This commit is contained in:
parent
28c390bc90
commit
f3f1c5aa32
@ -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({
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -60,6 +60,11 @@ export class SceneVariableSet extends SceneObjectBase<SceneVariableSetState> 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;
|
||||
|
@ -23,6 +23,7 @@ export interface TestVariableState extends MultiValueVariableState {
|
||||
export class TestVariable extends MultiValueVariable<TestVariableState> {
|
||||
private completeUpdate = new Subject<number>();
|
||||
public isGettingValues = true;
|
||||
public getValueOptionsCount = 0;
|
||||
|
||||
protected _variableDependency = new VariableDependencyConfig(this, {
|
||||
statePaths: ['query'],
|
||||
@ -42,10 +43,12 @@ export class TestVariable extends MultiValueVariable<TestVariableState> {
|
||||
public getValueOptions(args: VariableGetOptionsArgs): Observable<VariableValueOption[]> {
|
||||
const { delayMs } = this.state;
|
||||
|
||||
this.getValueOptionsCount += 1;
|
||||
|
||||
return new Observable<VariableValueOption[]>((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<TestVariableState> {
|
||||
this.isGettingValues = true;
|
||||
|
||||
return () => {
|
||||
sub.unsubscribe();
|
||||
clearTimeout(timeout);
|
||||
this.isGettingValues = false;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user