[EsAggs] Freeze cached responses to avoid response mutation#222160
[EsAggs] Freeze cached responses to avoid response mutation#222160ppisljar merged 21 commits intoelastic:mainfrom
Conversation
…nto search/freeze_response
|
Pinging @elastic/kibana-visualizations (Team:Visualizations) |
There was a problem hiding this comment.
Pull Request Overview
This PR ensures search responses and data structures are not mutated by introducing immutable operations and deep freezing cached responses, and fixes related bugs in maps, other buckets aggregation, and Vega data handling.
- Replace in-place
reverse()calls with non-mutating clones before reversing. - Add
structuredClonebefore modifying feature collections, aggregation responses, and Vega raw responses. - Introduce
deepFreezeon search interceptor responses to catch unintended mutations early.
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| x-pack/platform/plugins/shared/maps/.../es_search_source.tsx | Use slice().reverse() instead of mutating reverse() |
| x-pack/platform/plugins/shared/maps/.../geojson_source_data.tsx | Clone GeoJSON before assigning feature IDs |
| src/platform/plugins/shared/data/tsconfig.json | Add @kbn/std for deepFreeze and structuredClone support |
| src/platform/plugins/shared/data/public/.../search_interceptor.ts | Deep-freeze search responses |
| src/platform/plugins/shared/data/common/.../_terms_other_bucket_helper.ts | Clone both responses before merging "other" buckets |
| src/platform/plugins/shared/data/common/.../agg_configs.ts | Use structuredClone instead of cloneDeep |
| src/platform/plugins/private/vis_types/vega/.../search_api.ts | Clone raw Vega responses before exposing |
thomasneirynck
left a comment
There was a problem hiding this comment.
This has a real potential to introduce a severe performance hit. Especially when doing this for every response (imagine deep-cloning arbitrary table results for Discover).
What's the context of this fix? Why does it require cloning?
.../shared/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_source_data.tsx
Outdated
Show resolved
Hide resolved
src/platform/plugins/shared/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts
Outdated
Show resolved
Hide resolved
💚 Build Succeeded
Metrics [docs]Async chunks
Page load bundle
History
|
|
I wonder if we can get nearly the same benefit without the performance hit if we use a type-based compile-time approach instead of runtime. We could mark |
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
Async chunks
Page load bundle
History
|
nreese
left a comment
There was a problem hiding this comment.
kibana-presentation changes LGTM
code review only
|
Starting backport for target branches: 8.19, 9.1 https://github.com/elastic/kibana/actions/runs/15926901120 |
(cherry picked from commit 180f90a)
(cherry picked from commit 180f90a)
💚 All backports created successfully
Note: Successful backport PRs will be merged automatically after passing CI. Questions ?Please refer to the Backport tool documentation |
…22160) (#225634) # Backport This will backport the following commits from `main` to `9.1`: - [freeze response (#222160)](#222160) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Peter Pisljar","email":"peter.pisljar@elastic.co"},"sourceCommit":{"committedDate":"2025-06-27T13:00:07Z","message":"freeze response (#222160)","sha":"180f90a65cdd3edd4f9a215533aee1a0477436df","branchLabelMapping":{"^v9.2.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","Team:Visualizations","release_note:skip","backport:version","v9.1.0","v8.19.0","v9.2.0"],"title":"[EsAggs] Freeze cached responses to avoid response mutation","number":222160,"url":"https://github.com/elastic/kibana/pull/222160","mergeCommit":{"message":"freeze response (#222160)","sha":"180f90a65cdd3edd4f9a215533aee1a0477436df"}},"sourceBranch":"main","suggestedTargetBranches":["9.1","8.19"],"targetPullRequestStates":[{"branch":"9.1","label":"v9.1.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.2.0","branchLabelMappingKey":"^v9.2.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/222160","number":222160,"mergeCommit":{"message":"freeze response (#222160)","sha":"180f90a65cdd3edd4f9a215533aee1a0477436df"}}]}] BACKPORT--> Co-authored-by: Peter Pisljar <peter.pisljar@elastic.co> Co-authored-by: Marco Vettorello <marco.vettorello@elastic.co>
|
Looks like this PR has backport PRs but they still haven't been merged. Please merge them ASAP to keep the branches relatively in sync. |
4 similar comments
|
Looks like this PR has backport PRs but they still haven't been merged. Please merge them ASAP to keep the branches relatively in sync. |
|
Looks like this PR has backport PRs but they still haven't been merged. Please merge them ASAP to keep the branches relatively in sync. |
|
Looks like this PR has backport PRs but they still haven't been merged. Please merge them ASAP to keep the branches relatively in sync. |
|
Looks like this PR has backport PRs but they still haven't been merged. Please merge them ASAP to keep the branches relatively in sync. |
Summary
resolves #221886
also fixes 4 other bugs (other bucket, maps (2x), vega where we are modifying the response
also adds deep freeze on the search service cache object, so we can catch this problems earlier.
story: search service caches responses from elasticsearch, and next time we are to make the same request we get the response from cache. But if anyone who gets access to this object modifies it, the cached version gets modified, which might break the processing for the consumer that retrieves the cached version after it has been altered.
in order to prevent it we should: