diff --git a/packages/scenes/src/querying/SceneDataTransformer.test.ts b/packages/scenes/src/querying/SceneDataTransformer.test.ts index 1e05da6bb..a23547fd3 100644 --- a/packages/scenes/src/querying/SceneDataTransformer.test.ts +++ b/packages/scenes/src/querying/SceneDataTransformer.test.ts @@ -738,6 +738,92 @@ describe('SceneDataTransformer', () => { expect(customTransformerSpy).toHaveBeenCalledTimes(1); expect(transformer.state.data?.state).toBe(LoadingState.Loading); }); + + it('emits updated metadata when transformed frame references are unchanged', async () => { + const series = [arrayToDataFrame([1, 2, 3])]; + const annotations: DataFrame[] = []; + const dataNode = new SceneDataNode({ + data: { + state: LoadingState.Done, + timeRange: getDefaultTimeRange(), + request: { requestId: 'SQR100' } as DataQueryRequest, + series, + annotations, + }, + }); + + const transformer = new SceneDataTransformer({ + $data: dataNode, + transformations: [customTransformOperator], + }); + + const results: PanelData[] = []; + transformer.getResultsStream().subscribe((result) => { + results.push(result.data); + }); + + transformer.activate(); + + await new Promise((r) => setTimeout(r, 1)); + + const initialResult = results[0]; + + dataNode.setState({ + data: { + ...dataNode.state.data, + state: LoadingState.Loading, + request: { requestId: 'SQR101' } as DataQueryRequest, + }, + }); + + await new Promise((r) => setTimeout(r, 1)); + + expect(customTransformerSpy).toHaveBeenCalledTimes(1); + expect(results).toHaveLength(2); + expect(results[1].state).toBe(LoadingState.Loading); + expect(results[1].request?.requestId).toBe('SQR101'); + expect(results[1].series).toBe(initialResult.series); + expect(results[1].annotations).toBe(initialResult.annotations); + }); + + it('does not emit when transformed frame references and metadata are unchanged', async () => { + const series = [arrayToDataFrame([1, 2, 3])]; + const annotations: DataFrame[] = []; + const dataNode = new SceneDataNode({ + data: { + state: LoadingState.Done, + timeRange: getDefaultTimeRange(), + request: { requestId: 'SQR100' } as DataQueryRequest, + series, + annotations, + }, + }); + + const transformer = new SceneDataTransformer({ + $data: dataNode, + transformations: [customTransformOperator], + }); + + const results: PanelData[] = []; + transformer.getResultsStream().subscribe((result) => { + results.push(result.data); + }); + + transformer.activate(); + + await new Promise((r) => setTimeout(r, 1)); + + dataNode.setState({ + data: { + ...dataNode.state.data, + }, + }); + + await new Promise((r) => setTimeout(r, 1)); + + expect(customTransformerSpy).toHaveBeenCalledTimes(1); + expect(results).toHaveLength(1); + }); }); it('interpolates transformation options before applying', () => { diff --git a/packages/scenes/src/querying/SceneDataTransformer.ts b/packages/scenes/src/querying/SceneDataTransformer.ts index c504c7cf1..6593c4b8d 100644 --- a/packages/scenes/src/querying/SceneDataTransformer.ts +++ b/packages/scenes/src/querying/SceneDataTransformer.ts @@ -1,3 +1,4 @@ +import { isEqual } from 'lodash'; import { CustomTransformOperator, DataFrame, @@ -177,9 +178,27 @@ export class SceneDataTransformer extends SceneObjectBase