From b6f265f6f47df24b99a8130b1e0c889852f1d482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ida=20=C5=A0tambuk?= Date: Tue, 12 Mar 2024 16:14:46 +0100 Subject: [PATCH] asyncQueryDataSupport: always run queries asynchronously (#30) - Removes feature toggle for async queries --- CHANGELOG.md | 4 +++ package.json | 2 +- src/DatasourceWithAsyncBackend.test.ts | 32 +++++-------------- src/DatasourceWithAsyncBackend.ts | 32 ++++++++----------- src/RunQueryButtons.test.tsx | 33 +++++++------------ src/RunQueryButtons.tsx | 44 ++++++++++++-------------- 6 files changed, 59 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 158fb0e..d4df3d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## v0.2.0 + +- Remove athenaAsyncQueryDataSupport and redshiftAsyncQueryData feature toggle-related code + ## v0.1.11 - Support Node 18 (#25) diff --git a/package.json b/package.json index 740e4d2..ecc4ccf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@grafana/async-query-data", - "version": "0.1.11", + "version": "0.2.0", "description": "Async query support for Grafana", "main": "dist/index.js", "scripts": { diff --git a/src/DatasourceWithAsyncBackend.test.ts b/src/DatasourceWithAsyncBackend.test.ts index fda7a01..b0b7746 100644 --- a/src/DatasourceWithAsyncBackend.test.ts +++ b/src/DatasourceWithAsyncBackend.test.ts @@ -62,13 +62,8 @@ const defaultRequest = { startTime: 0, }; -const setupDatasourceWithAsyncBackend = ({ - settings = defaultInstanceSettings, - asyncQueryDataSupport = true, -}: { - settings?: DataSourceInstanceSettings<{}>; - asyncQueryDataSupport?: boolean; -}) => new DatasourceWithAsyncBackend(settings, asyncQueryDataSupport); +const setupDatasourceWithAsyncBackend = (settings: DataSourceInstanceSettings = defaultInstanceSettings) => + new DatasourceWithAsyncBackend(settings); describe('DatasourceWithAsyncBackend', () => { // beforeAll(() => { @@ -76,14 +71,14 @@ describe('DatasourceWithAsyncBackend', () => { // }); it('can store running queries', () => { - const ds = setupDatasourceWithAsyncBackend({}); + const ds = setupDatasourceWithAsyncBackend(); ds.storeQuery(defaultQuery, { queryID: '123' }); expect(ds.getQuery(defaultQuery)).toEqual({ queryID: '123' }); }); it('can remove running queries', () => { - const ds = setupDatasourceWithAsyncBackend({}); + const ds = setupDatasourceWithAsyncBackend(); ds.storeQuery(defaultQuery, { queryID: '123' }); expect(ds.getQuery(defaultQuery)).toEqual({ queryID: '123' }); @@ -92,15 +87,15 @@ describe('DatasourceWithAsyncBackend', () => { }); it('can cancel running queries', () => { - const ds = setupDatasourceWithAsyncBackend({}); + const ds = setupDatasourceWithAsyncBackend(); ds.storeQuery(defaultQuery, { queryID: '123' }); ds.cancel(defaultQuery); expect(ds.getQuery(defaultQuery)).toEqual({ queryID: '123', shouldCancel: true }); }); - it('can queue individual queries to run asynchronously if feature toggle asyncQueryDataSupport is `true`', () => { - const ds = setupDatasourceWithAsyncBackend({ asyncQueryDataSupport: true }); + it('will queue individual queries to run asynchronously', () => { + const ds = setupDatasourceWithAsyncBackend(); ds.doSingle = jest.fn().mockReturnValue(Promise.resolve({ data: [] })); expect(ds.doSingle).not.toHaveBeenCalled(); @@ -110,19 +105,8 @@ describe('DatasourceWithAsyncBackend', () => { expect(ds.doSingle).toHaveBeenCalledWith(defaultQuery2, defaultRequest); }); - it('can run queries synchronously if feature toggle asyncQueryDataSupport is `false`', () => { - const ds = setupDatasourceWithAsyncBackend({ asyncQueryDataSupport: false }); - - ds.doSingle = jest.fn(); - expect(ds.doSingle).not.toHaveBeenCalled(); - ds.query(defaultRequest); - expect(ds.doSingle).not.toHaveBeenCalled(); - expect(queryMock).toHaveBeenCalledTimes(1); - expect(queryMock).toHaveBeenCalledWith(defaultRequest); - }); - it('uses the datasource id for the request id', () => { - const ds = setupDatasourceWithAsyncBackend({ asyncQueryDataSupport: true }); + const ds = setupDatasourceWithAsyncBackend(); expect(getRequestLooperMock).not.toHaveBeenCalled(); ds.doSingle(defaultQuery, defaultRequest); expect(getRequestLooperMock).toHaveBeenCalledTimes(1); diff --git a/src/DatasourceWithAsyncBackend.ts b/src/DatasourceWithAsyncBackend.ts index a5580e2..9a71ea4 100644 --- a/src/DatasourceWithAsyncBackend.ts +++ b/src/DatasourceWithAsyncBackend.ts @@ -39,36 +39,30 @@ const isCustomMeta = (meta: unknown): meta is CustomMeta => { export class DatasourceWithAsyncBackend< TQuery extends DataQuery = DataQuery, - TOptions extends DataSourceJsonData = DataSourceJsonData + TOptions extends DataSourceJsonData = DataSourceJsonData, > extends DataSourceWithBackend { private runningQueries: { [hash: string]: RunningQueryInfo } = {}; private requestCounter = 100; - private asyncQueryDataSupport: boolean; private requestIdPrefix: number; - constructor(instanceSettings: DataSourceInstanceSettings, asyncQueryDataSupport = false) { + constructor(instanceSettings: DataSourceInstanceSettings) { super(instanceSettings); this.requestIdPrefix = instanceSettings.id; - this.asyncQueryDataSupport = asyncQueryDataSupport; } query(request: DataQueryRequest): Observable { - if (this.asyncQueryDataSupport) { - const targets = this.filterQuery ? request.targets.filter(this.filterQuery) : request.targets; - if (!targets.length) { - return of({ data: [] }); - } - const all: Array> = []; - for (let target of targets) { - if (target.hide) { - continue; - } - all.push(this.doSingle(target, request)); + const targets = this.filterQuery ? request.targets.filter(this.filterQuery) : request.targets; + if (!targets.length) { + return of({ data: [] }); + } + const all: Array> = []; + for (let target of targets) { + if (target.hide) { + continue; } - return merge(...all); - } else { - return super.query(request); + all.push(this.doSingle(target, request)); } + return merge(...all); } storeQuery(target: TQuery, queryInfo: RunningQueryInfo) { @@ -123,7 +117,7 @@ export class DatasourceWithAsyncBackend< const [_query] = targets; const query: TQuery & DataQueryMeta = { ..._query, - ...(this.asyncQueryDataSupport ? { meta: { queryFlow: 'async' } } : {}), + meta: { queryFlow: 'async' }, }; const data = { diff --git a/src/RunQueryButtons.test.tsx b/src/RunQueryButtons.test.tsx index af09452..b0f3794 100644 --- a/src/RunQueryButtons.test.tsx +++ b/src/RunQueryButtons.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {fireEvent, render, screen} from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import { DataQuery } from '@grafana/data'; import { RunQueryButtons, RunQueryButtonsProps } from './RunQueryButtons'; @@ -15,38 +15,29 @@ const getDefaultProps = (overrides?: Partial>) = }; describe('RunQueryButtons', () => { + it('renders the `Run` and `Stop` buttons', () => { + const props = getDefaultProps(); + render(); + const runButton = screen.getByRole('button', { name: 'Run query' }); + expect(runButton).toBeInTheDocument(); + const stopButton = screen.queryByRole('button', { name: 'Stop query' }); + expect(stopButton).toBeInTheDocument(); + }); + it('disable the run button if the if the enableRun button is false', () => { - const props = getDefaultProps({ enableRun: false}); + const props = getDefaultProps({ enableRun: false }); render(); const runButton = screen.getByRole('button', { name: 'Run query' }); expect(runButton).toBeDisabled(); }); it('run button should be enabled if the enableRun button is true', () => { - const props = getDefaultProps({ enableRun: true}); + const props = getDefaultProps({ enableRun: true }); render(); const runButton = screen.getByRole('button', { name: 'Run query' }); expect(runButton).not.toBeDisabled(); }); - it('only renders the `Run` button if onCancelQuery is undefined', () => { - const props = getDefaultProps({ onCancelQuery: undefined }); - render(); - const runButton = screen.getByRole('button', { name: 'Run query' }); - expect(runButton).toBeInTheDocument(); - const stopButton = screen.queryByRole('button', { name: 'Stop query' }); - expect(stopButton).not.toBeInTheDocument(); - }); - - it('renders the `Run` and `Stop` buttons if onCancelQuery defined', () => { - const props = getDefaultProps(); - render(); - const runButton = screen.getByRole('button', { name: 'Run query' }); - expect(runButton).toBeInTheDocument(); - const stopButton = screen.queryByRole('button', { name: 'Stop query' }); - expect(stopButton).toBeInTheDocument(); - }); - it('Stop query button should be disabled until run button is clicked', () => { const props = getDefaultProps(); render(); diff --git a/src/RunQueryButtons.tsx b/src/RunQueryButtons.tsx index eb2e10d..90efa16 100644 --- a/src/RunQueryButtons.tsx +++ b/src/RunQueryButtons.tsx @@ -5,7 +5,7 @@ import { DataQuery, LoadingState } from '@grafana/data'; export interface RunQueryButtonsProps { enableRun?: boolean; onRunQuery: () => void; - onCancelQuery?: (query: TQuery) => void; + onCancelQuery: (query: TQuery) => void; query: TQuery; state?: LoadingState; } @@ -40,27 +40,25 @@ export const RunQueryButtons = (props: RunQueryButtons : undefined; return ( - <> - - {onCancelQuery && - - } - + <> + + + ); };