Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Code
a0e2dc6903 test(caching): pin cache-key stability against extra_cache_keys order
This is a test-only PR opened as a TDD-style validation of issue #34543.

#34543 (filed 2025-08) reports that embedded dashboards with multiple
Jinja url_param() filters fail async cache retrieval with a 422 "Error
loading data from cache", while a single url_param works fine.

Root cause: SqlaTable.get_extra_cache_keys() (superset/connectors/sqla/models.py)
returns list(set(extra_cache_keys)). Python randomizes string hashing
per-process, so the same set of url_param values can iterate in a
different order in the Celery worker (which writes the query results
to cache) than in the web process (which re-derives the cache key to
read them back). hash_from_dict() only sorts dict keys, not list
values, so two extra_cache_keys lists with identical values but
different order hash to different cache keys. A single-element list
has only one possible order, which is why the bug only appears with
multiple parameters.

This PR adds one regression test on QueryObject.cache_key():

1. test_cache_key_stable_regardless_of_extra_cache_keys_order -
   asserts the cache key is identical for two otherwise-equal query
   objects whose extra_cache_keys differ only in order.

Closes #34543

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 17:51:00 -07:00

View File

@@ -86,6 +86,34 @@ def test_cache_key_changes_for_new_query_object_different_params():
assert query_object2.cache_key() != cache_key1
def test_cache_key_stable_regardless_of_extra_cache_keys_order():
"""
Regression for #34543: the cache key must not depend on the order of
``extra_cache_keys``.
``SqlaTable.get_extra_cache_keys`` (superset/connectors/sqla/models.py)
returns ``list(set(extra_cache_keys))``. Python's string hashing is
randomized per-process (``PYTHONHASHSEED``), so the same set of values
can iterate in a different order in the Celery worker process (which
writes the query results to cache) than in the web process (which
re-derives the cache key to read them back). Because ``hash_from_dict``
only sorts dict keys and not list values, two ``extra_cache_keys`` lists
with identical Jinja ``url_param()`` values but different order hash to
different cache keys, causing async chart-data lookups to 422 with
"Error loading data from cache" whenever more than one url_param is
referenced (a single-element list has only one possible order, which is
why the bug is only visible with multiple parameters).
"""
query_object1 = QueryObject(row_limit=1)
query_object2 = QueryObject(row_limit=1)
same_values_different_order = ["CAR_IDS=1,2,3", "CHASSIS_IDS=100,200"]
cache_key1 = query_object1.cache_key(extra_cache_keys=same_values_different_order)
cache_key2 = query_object2.cache_key(
extra_cache_keys=list(reversed(same_values_different_order))
)
assert cache_key1 == cache_key2
def test_cache_key_changes_for_new_query_object_same_params():
"""
When a new query object is created with the same params,