Skip to content

Commit c78cb2d

Browse files
iwysiukevinwcyu
andauthored
Prefix requestId with data source id (#27)
Co-authored-by: Kevin Yu <kevinwcyu@users.noreply.github.com>
1 parent 1a7c93f commit c78cb2d

File tree

3 files changed

+84
-10
lines changed

3 files changed

+84
-10
lines changed

src/DatasourceWithAsyncBackend.test.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
1-
import { DataQuery, DataSourceInstanceSettings, PluginType, getDefaultTimeRange } from '@grafana/data';
1+
import {
2+
DataQuery,
3+
DataQueryRequest,
4+
DataSourceInstanceSettings,
5+
PluginType,
6+
getDefaultTimeRange,
7+
} from '@grafana/data';
28
import { DataSourceWithBackend } from '@grafana/runtime';
39
import { DatasourceWithAsyncBackend } from './DatasourceWithAsyncBackend';
10+
import { RequestLoopOptions } from 'requestLooper';
411

512
const queryMock = jest.fn().mockImplementation(() => Promise.resolve({ data: [] }));
613
jest.spyOn(DataSourceWithBackend.prototype, 'query').mockImplementation(queryMock);
714

15+
const getRequestLooperMock = jest.fn();
16+
jest.mock('./requestLooper.ts', () => ({
17+
...jest.requireActual('./requestLooper.ts'),
18+
getRequestLooper: (req: DataQueryRequest, options: RequestLoopOptions) => getRequestLooperMock(req, options),
19+
}));
20+
821
const defaultInstanceSettings: DataSourceInstanceSettings<{}> = {
9-
id: 1,
22+
id: 12,
1023
uid: 'test',
1124
type: 'test',
1225
name: 'test',
@@ -33,6 +46,7 @@ const defaultInstanceSettings: DataSourceInstanceSettings<{}> = {
3346
},
3447
access: 'direct',
3548
jsonData: {},
49+
readOnly: false,
3650
};
3751
const defaultQuery = { refId: 'refId-1' };
3852
const defaultQuery2 = { refId: 'refId-2' };
@@ -106,4 +120,17 @@ describe('DatasourceWithAsyncBackend', () => {
106120
expect(queryMock).toHaveBeenCalledTimes(1);
107121
expect(queryMock).toHaveBeenCalledWith(defaultRequest);
108122
});
123+
124+
it('uses the datasource id for the request id', () => {
125+
const ds = setupDatasourceWithAsyncBackend({ asyncQueryDataSupport: true });
126+
expect(getRequestLooperMock).not.toHaveBeenCalled();
127+
ds.doSingle(defaultQuery, defaultRequest);
128+
expect(getRequestLooperMock).toHaveBeenCalledTimes(1);
129+
const expectedRequest = {
130+
...defaultRequest,
131+
targets: [defaultQuery],
132+
requestId: '12_100',
133+
};
134+
expect(getRequestLooperMock).toHaveBeenCalledWith(expectedRequest, expect.anything());
135+
});
109136
});

src/DatasourceWithAsyncBackend.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@ import {
66
DataSourceInstanceSettings,
77
DataSourceJsonData,
88
} from '@grafana/data';
9-
import { BackendDataSourceResponse, DataSourceWithBackend, config, getBackendSrv, toDataQueryResponse } from '@grafana/runtime';
9+
import {
10+
BackendDataSourceResponse,
11+
DataSourceWithBackend,
12+
config,
13+
getBackendSrv,
14+
toDataQueryResponse,
15+
} from '@grafana/runtime';
1016
import { merge, Observable, of } from 'rxjs';
11-
import { catchError,map } from 'rxjs/operators';
17+
import { catchError, map } from 'rxjs/operators';
1218
import { getRequestLooper } from './requestLooper';
1319

1420
export interface CustomMeta {
@@ -38,9 +44,11 @@ export class DatasourceWithAsyncBackend<
3844
private runningQueries: { [hash: string]: RunningQueryInfo } = {};
3945
private requestCounter = 100;
4046
private asyncQueryDataSupport: boolean;
47+
private requestIdPrefix: number;
4148

4249
constructor(instanceSettings: DataSourceInstanceSettings<TOptions>, asyncQueryDataSupport = false) {
4350
super(instanceSettings);
51+
this.requestIdPrefix = instanceSettings.id;
4452
this.asyncQueryDataSupport = asyncQueryDataSupport;
4553
}
4654

@@ -85,7 +93,7 @@ export class DatasourceWithAsyncBackend<
8593
let allData: DataFrame[] = [];
8694

8795
return getRequestLooper(
88-
{ ...request, targets: [target], requestId: `aws_ts_${this.requestCounter++}` },
96+
{ ...request, targets: [target], requestId: `${this.requestIdPrefix}_${this.requestCounter++}` },
8997
{
9098
/**
9199
* Additional query to execute if the current query is still in a running state
@@ -136,7 +144,8 @@ export class DatasourceWithAsyncBackend<
136144
};
137145

138146
let headers = {};
139-
const cachingDisabled = !config.featureToggles.useCachingService || !config.featureToggles.awsAsyncQueryCaching
147+
const cachingDisabled =
148+
!config.featureToggles.useCachingService || !config.featureToggles.awsAsyncQueryCaching;
140149
if (cachingDisabled && isRunning(status)) {
141150
// bypass query caching for Grafana Enterprise to
142151
// prevent an infinite loop
@@ -152,9 +161,12 @@ export class DatasourceWithAsyncBackend<
152161

153162
return getBackendSrv()
154163
.fetch<BackendDataSourceResponse>(options)
155-
.pipe(map((result) => ({ data: toDataQueryResponse(result).data })), catchError((err) => {
156-
return of(toDataQueryResponse(err));
157-
}));
164+
.pipe(
165+
map((result) => ({ data: toDataQueryResponse(result).data })),
166+
catchError((err) => {
167+
return of(toDataQueryResponse(err));
168+
})
169+
);
158170
},
159171

160172
/**

src/requestLooper.test.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { RequestLoopOptions, getRequestLooper } from 'requestLooper';
22
import { TestScheduler } from 'rxjs/testing';
3-
import { getDefaultTimeRange, DataQuery, LoadingState } from '@grafana/data';
3+
import { of } from 'rxjs';
4+
import { getDefaultTimeRange, DataQuery, LoadingState, DataQueryRequest } from '@grafana/data';
45

56
const mockQuery: DataQuery = {
67
refId: '',
@@ -90,4 +91,38 @@ describe('requestLooper', () => {
9091
scheduler.flush();
9192
expect(onCancel).toBeCalledTimes(1);
9293
});
94+
95+
it('increments the request id', (done) => {
96+
let requestIds: string[] = [];
97+
98+
const queryMock = jest.fn().mockImplementation((req: DataQueryRequest) => {
99+
requestIds.push(req.requestId);
100+
return of({ data: [], state: LoadingState.Loading, meta });
101+
});
102+
103+
const opt: RequestLoopOptions = {
104+
getNextQuery: jest
105+
.fn()
106+
.mockImplementationOnce(() => ({ ...mockQuery, queryId: 'queryId' }))
107+
.mockImplementationOnce(() => ({ ...mockQuery, queryId: 'queryId' }))
108+
.mockImplementationOnce(() => undefined),
109+
query: (req) => queryMock(req),
110+
onCancel: jest.fn(),
111+
process: jest.fn().mockImplementation(() => []),
112+
shouldCancel: jest.fn().mockImplementation(() => false),
113+
};
114+
115+
const looper = getRequestLooper(request, opt);
116+
117+
looper.subscribe({
118+
next: () => {},
119+
complete: () => {
120+
expect(requestIds).toHaveLength(3);
121+
expect(requestIds[0]).toBe(request.requestId);
122+
expect(requestIds[1]).toBe(request.requestId + '.2');
123+
expect(requestIds[2]).toBe(request.requestId + '.3');
124+
done();
125+
},
126+
});
127+
});
93128
});

0 commit comments

Comments
 (0)