Live: support streaming results out-of-the-box (#32821)

This commit is contained in:
Ryan McKinley
2021-04-09 21:17:22 +02:00
committed by GitHub
parent 2d7e980da7
commit b96e45299d
20 changed files with 179 additions and 242 deletions
@@ -7,11 +7,15 @@ import {
DataSourceJsonData,
ScopedVars,
makeClassES5Compatible,
DataFrame,
parseLiveChannelAddress,
StreamingFrameOptions,
} from '@grafana/data';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { merge, Observable, of } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
import { getBackendSrv, getDataSourceSrv } from '../services';
import { BackendDataSourceResponse, toDataQueryResponse } from './queryResponse';
import { getLiveDataStream } from './liveQuery';
const ExpressionDatasourceID = '__expr__';
@@ -132,8 +136,13 @@ class DataSourceWithBackend<
requestId,
})
.pipe(
map((rsp) => {
return toDataQueryResponse(rsp, queries as DataQuery[]);
switchMap((raw) => {
const rsp = toDataQueryResponse(raw, queries as DataQuery[]);
// Check if any response should subscribe to a live stream
if (rsp.data?.length && rsp.data.find((f: DataFrame) => f.meta?.channel)) {
return toStreamingDataResponse(request, rsp);
}
return of(rsp);
}),
catchError((err) => {
return of(toDataQueryResponse(err));
@@ -209,6 +218,44 @@ class DataSourceWithBackend<
}
}
export function toStreamingDataResponse(
request: DataQueryRequest,
rsp: DataQueryResponse
): Observable<DataQueryResponse> {
const buffer: StreamingFrameOptions = {
maxLength: request.maxDataPoints ?? 500,
};
// For recent queries, clamp to the current time range
if (request.rangeRaw?.to === 'now') {
buffer.maxDelta = request.range.to.valueOf() - request.range.from.valueOf();
}
const staticdata: DataFrame[] = [];
const streams: Array<Observable<DataQueryResponse>> = [];
for (const frame of rsp.data) {
const addr = parseLiveChannelAddress(frame.meta?.channel);
if (addr) {
streams.push(
getLiveDataStream({
addr,
buffer,
frame: frame as DataFrame,
})
);
} else {
staticdata.push(frame);
}
}
if (staticdata.length) {
streams.push(of({ ...rsp, data: staticdata }));
}
if (streams.length === 1) {
return streams[0]; // avoid merge wrapper
}
return merge(...streams);
}
//@ts-ignore
DataSourceWithBackend = makeClassES5Compatible(DataSourceWithBackend);