Live: move centrifuge service to a web worker (#41090)

* Fix: make webpack pickup workers written in TS

* Add comlink to dependencies

* Temporary fix: copy paste `toDataQueryError` from @grafana/runtime to avoid web dependencies

* Implemented comlink-based centrifuge worker & worker proxy

* Temporary fix: implement comlink transferHandlers for subscriptions and streamingdataframes

* Move liveTimer filtering from CentrifugeService into GrafanaLiveService

* Switch from CentrifugeService to CentrifugeServiceWorkerProxy in GrafanaLive

* Naming fix

* Refactor: move liveTimer-based data filtering from GrafanaLiveService to CentrifugeServiceWorker

* observe dataStream on an async scheduler

* Fix: - Unsubscribe is now propagated from the main thread to the worker, - improve worker&workerProxy types

* Fix: Prettify types

* Fix: Add error & complete observers

* Docs: Add comment explaining the `subscriberTransferHandler`

* Fix: Replace `StreamingDataFrameHandler` with explicitly converting StreamingDataFrame to a DataFrameDTO

* Refactor: move liveTimer filtering to service.ts to make it easy to implement a `live-service-web-worker` feature flag

* Feat: add `live-service-web-worker` feature flag

* Fix: extract toDataQueryError.ts to a separate file within `@grafana-runtime` to avoid having a dependency from webworker to the whole package (@grafana-runtime/index.ts)

* Update public/app/features/dashboard/dashgrid/liveTimer.ts

Co-authored-by: Leon Sorokin <leeoniya@gmail.com>

* Fix: fixed default import class in worker file

* Fix: cast worker as Endpoint

* Migrate from worker-loader to webpack native worker support v1 - broken prod build

* Fix: Use custom path in HtmlWebpackPlugin

* Fix: Loading workers from CDNs

* Fix: Avoid issues with jest ESM support by mocking `createWorker` files

* Fix: move the custom mockWorker rendering layout to `test/mocks`

Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
Artur Wierzbicki
2021-11-09 21:05:01 +04:00
committed by GitHub
parent e2ed140de2
commit f45eb309ef
23 changed files with 387 additions and 92 deletions

View File

@@ -17,12 +17,12 @@ export {
StreamOptionsProvider,
} from './utils/DataSourceWithBackend';
export {
toDataQueryError,
toDataQueryResponse,
frameToMetricFindValue,
BackendDataSourceResponse,
DataResponse,
} from './utils/queryResponse';
export { toDataQueryError } from './utils/toDataQueryError';
export { PanelRenderer, PanelRendererProps, PanelRendererType, setPanelRenderer } from './components/PanelRenderer';
export { setQueryRunnerFactory, createQueryRunner, QueryRunnerFactory } from './services/QueryRunner';
export { DataSourcePicker, DataSourcePickerProps, DataSourcePickerState } from './components/DataSourcePicker';

View File

@@ -14,6 +14,7 @@ import {
dataFrameFromJSON,
} from '@grafana/data';
import { FetchError, FetchResponse } from '../services';
import { toDataQueryError } from './toDataQueryError';
/**
* Single response object from a backend data source. Properties are optional but response should contain at least
@@ -159,36 +160,6 @@ export function toTestingStatus(err: FetchError): any {
throw err;
}
/**
* Convert an object into a DataQueryError -- if this is an HTTP response,
* it will put the correct values in the error field
*
* @public
*/
export function toDataQueryError(err: DataQueryError | string | Object): DataQueryError {
const error = (err || {}) as DataQueryError;
if (!error.message) {
if (typeof err === 'string' || err instanceof String) {
return { message: err } as DataQueryError;
}
let message = 'Query error';
if (error.message) {
message = error.message;
} else if (error.data && error.data.message) {
message = error.data.message;
} else if (error.data && error.data.error) {
message = error.data.error;
} else if (error.status) {
message = `Query error: ${error.status} ${error.statusText}`;
}
error.message = message;
}
return error;
}
/**
* Return the first string or non-time field as the value
*

View File

@@ -0,0 +1,31 @@
import { DataQueryError } from '@grafana/data';
/**
* Convert an object into a DataQueryError -- if this is an HTTP response,
* it will put the correct values in the error field
*
* @public
*/
export function toDataQueryError(err: DataQueryError | string | Object): DataQueryError {
const error = (err || {}) as DataQueryError;
if (!error.message) {
if (typeof err === 'string' || err instanceof String) {
return { message: err } as DataQueryError;
}
let message = 'Query error';
if (error.message) {
message = error.message;
} else if (error.data && error.data.message) {
message = error.data.message;
} else if (error.data && error.data.error) {
message = error.data.error;
} else if (error.status) {
message = `Query error: ${error.status} ${error.statusText}`;
}
error.message = message;
}
return error;
}