Revert "MixedDataSource: Support multi value data source variable that issues a query to each data source" (#87579)

Revert "MixedDataSource: Support multi value data source variable that issues…"

This reverts commit 700d378c98.
This commit is contained in:
Kristina 2024-05-09 16:16:28 -05:00 committed by GitHub
parent a6a9ab4008
commit 979d87f46f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 151 deletions

View File

@ -2,11 +2,7 @@ import { lastValueFrom } from 'rxjs';
import { getQueryOptions } from 'test/helpers/getQueryOptions';
import { DatasourceSrvMock, MockObservableDataSourceApi } from 'test/mocks/datasource_srv';
import { DataQueryRequest, DataSourceInstanceSettings, DataSourceRef, LoadingState } from '@grafana/data';
import { DataSourceSrv, setDataSourceSrv, setTemplateSrv } from '@grafana/runtime';
import { CustomVariable, SceneFlexLayout, SceneVariableSet } from '@grafana/scenes';
import { TemplateSrv } from '../../../features/templating/template_srv';
import { DataQueryRequest, DataSourceInstanceSettings, LoadingState } from '@grafana/data';
import { MIXED_DATASOURCE_NAME } from './MixedDataSource';
import { MixedDatasource } from './module';
@ -25,19 +21,13 @@ const datasourceSrv = new DatasourceSrvMock(defaultDS, {
]),
});
describe('MixedDatasource', () => {
beforeEach(() => {
jest.clearAllMocks();
setDataSourceSrv({
...datasourceSrv,
get: (uid: DataSourceRef) => datasourceSrv.get(uid),
getInstanceSettings: jest.fn().mockReturnValue({ meta: {} }),
getList: jest.fn(),
reload: jest.fn(),
});
setTemplateSrv(new TemplateSrv());
});
const getDataSourceSrvMock = jest.fn().mockReturnValue(datasourceSrv);
jest.mock('@grafana/runtime', () => ({
...jest.requireActual('@grafana/runtime'),
getDataSourceSrv: () => getDataSourceSrvMock(),
}));
describe('MixedDatasource', () => {
describe('with no errors', () => {
it('direct query should return results', async () => {
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
@ -93,67 +83,6 @@ describe('MixedDatasource', () => {
});
});
describe('with multi template variable', () => {
beforeAll(() => {
setDataSourceSrv({
getInstanceSettings() {
return {};
},
} as DataSourceSrv);
});
const scene = new SceneFlexLayout({
children: [],
$variables: new SceneVariableSet({
variables: [new CustomVariable({ name: 'ds', value: ['B', 'C'] })],
}),
});
it('should run query for each datasource when there is a multi value template variable', async () => {
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
const request = {
targets: [{ refId: 'AA', datasource: { uid: '$ds' } }],
scopedVars: {
__sceneObject: { value: scene },
},
} as unknown as DataQueryRequest;
await expect(ds.query(request)).toEmitValuesWith((results) => {
expect(results).toHaveLength(2);
expect(results[0].key).toBe('mixed-0-');
expect(results[0].state).toBe(LoadingState.Loading);
expect(results[1].key).toBe('mixed-1-');
expect(results[1].state).toBe(LoadingState.Done);
});
});
it('should run query for picked datasource and template variable datasource', async () => {
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
const request = {
targets: [
{ refId: 'AA', datasource: { uid: '$ds' } },
{ refId: 'BB', datasource: { uid: 'Loki' } },
],
scopedVars: {
__sceneObject: { value: scene },
},
} as unknown as DataQueryRequest;
await expect(ds.query(request)).toEmitValuesWith((results) => {
expect(results).toHaveLength(4);
expect(results[0].key).toBe('mixed-0-');
expect(results[0].state).toBe(LoadingState.Loading);
expect(results[1].key).toBe('mixed-1-');
expect(results[1].state).toBe(LoadingState.Loading);
expect(results[2].key).toBe('mixed-2-A');
expect(results[2].state).toBe(LoadingState.Loading);
expect(results[3].key).toBe('mixed-2-B');
expect(results[3].state).toBe(LoadingState.Done);
});
});
});
it('should return both query results from the same data source', async () => {
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
const request = {

View File

@ -10,10 +10,8 @@ import {
DataSourceApi,
DataSourceInstanceSettings,
LoadingState,
ScopedVars,
} from '@grafana/data';
import { getDataSourceSrv, getTemplateSrv, toDataQueryError } from '@grafana/runtime';
import { CustomFormatterVariable } from '@grafana/scenes';
import { getDataSourceSrv, toDataQueryError } from '@grafana/runtime';
export const MIXED_DATASOURCE_NAME = '-- Mixed --';
@ -21,8 +19,7 @@ export const mixedRequestId = (queryIdx: number, requestId?: string) => `mixed-$
export interface BatchedQueries {
datasource: Promise<DataSourceApi>;
queries: DataQuery[];
scopedVars: ScopedVars;
targets: DataQuery[];
}
export class MixedDatasource extends DataSourceApi<DataQuery> {
@ -42,77 +39,23 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
// Build groups of queries to run in parallel
const sets: { [key: string]: DataQuery[] } = groupBy(queries, 'datasource.uid');
const batches: BatchedQueries[] = [];
const mixed: BatchedQueries[] = [];
for (const key in sets) {
batches.push(...this.getBatchesForQueries(sets[key], request));
}
const targets = sets[key];
// Missing UIDs?
if (!batches.length) {
return of({ data: [] }); // nothing
}
return this.batchQueries(batches, request);
}
/**
* Almost always returns a single batch for each set of queries.
* Unless the query is using a multi value variable.
*/
private getBatchesForQueries(queries: DataQuery[], request: DataQueryRequest<DataQuery>) {
const dsRef = queries[0].datasource;
const batches: BatchedQueries[] = [];
// Using the templateSrv.replace function here with a custom formatter as that is the cleanest way
// to access the raw value or value array of a variable.
const datasourceUid = getTemplateSrv().replace(
dsRef?.uid,
request.scopedVars,
(value: string | string[], variable: CustomFormatterVariable) => {
// If it's not a data source variable, or single value
if (!Array.isArray(value)) {
batches.push({
datasource: getDataSourceSrv().get(queries[0].datasource, request.scopedVars),
queries,
scopedVars: request.scopedVars,
});
return;
}
for (const uid of value) {
if (uid === 'default') {
continue;
}
const dsSettings = getDataSourceSrv().getInstanceSettings(uid);
batches.push({
datasource: getDataSourceSrv().get(uid),
queries: cloneDeep(queries),
scopedVars: {
...request.scopedVars,
[variable.name]: { value: uid, text: dsSettings?.name },
},
});
}
return '';
}
);
if (datasourceUid !== '') {
batches.push({
datasource: getDataSourceSrv().get(datasourceUid),
queries: cloneDeep(queries),
scopedVars: {
...request.scopedVars,
},
mixed.push({
datasource: getDataSourceSrv().get(targets[0].datasource, request.scopedVars),
targets,
});
}
return batches;
// Missing UIDs?
if (!mixed.length) {
return of({ data: [] }); // nothing
}
return this.batchQueries(mixed, request);
}
batchQueries(mixed: BatchedQueries[], request: DataQueryRequest<DataQuery>): Observable<DataQueryResponse> {
@ -121,8 +64,7 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
mergeMap((api: DataSourceApi) => {
const dsRequest = cloneDeep(request);
dsRequest.requestId = mixedRequestId(i, dsRequest.requestId);
dsRequest.targets = query.queries;
dsRequest.scopedVars = query.scopedVars;
dsRequest.targets = query.targets;
return from(api.query(dsRequest)).pipe(
map((response) => {
@ -160,7 +102,7 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
}
private isQueryable(query: BatchedQueries): boolean {
return query && Array.isArray(query.queries) && query.queries.length > 0;
return query && Array.isArray(query.targets) && query.targets.length > 0;
}
private finalizeResponses(responses: DataQueryResponse[]): DataQueryResponse[] {