Skip to content

fix: Enforce per-user caching on legacy API endpoint#39789

Merged
Vitor-Avila merged 1 commit intomasterfrom
fix/legacy-per-user-caching
Apr 30, 2026
Merged

fix: Enforce per-user caching on legacy API endpoint#39789
Vitor-Avila merged 1 commit intomasterfrom
fix/legacy-per-user-caching

Conversation

@Vitor-Avila
Copy link
Copy Markdown
Contributor

SUMMARY

The /superset/explore_json/ endpoint was not respecting per-user caching, which can be enforced via FF and also required for DB connections authenticating with OAuth2.

This PR fixes the issue by moving the logic responsible for adding the cache keys to a helper that's used on both flows.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

No UI changes.

TESTING INSTRUCTIONS

Test coverage added. For manual testing:

  1. Enable the CACHE_QUERY_BY_USER FF.
  2. Create a chart, and load it using Account A.
  3. Access Superset using Account B, and validate this account doesn't use Account's A cache.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review Bot commented Apr 30, 2026

Code Review Agent Run #abcfce

Actionable Suggestions - 0
Review Details
  • Files reviewed - 6 · Commit Range: f41bca7..f41bca7
    • superset/common/query_object.py
    • superset/utils/cache_keys.py
    • superset/viz.py
    • tests/unit_tests/queries/query_object_test.py
    • tests/unit_tests/test_viz_cache_key.py
    • tests/unit_tests/utils/test_impersonation_cache_key.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@dosubot dosubot Bot added api Related to the REST API infra:caching Infra setup and configuration related to caching labels Apr 30, 2026
from superset.utils.core import override_user


def _flag(name: str):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add an explicit return type annotation to _flag so the helper has fully typed input and output. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The helper is only partially typed: name has a type annotation, but the function has no return type annotation.
This matches the suggested custom rule about fully typing new helper functions, so the violation is real.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_impersonation_cache_key.py
**Line:** 27:27
**Comment:**
	*Custom Rule: Add an explicit return type annotation to `_flag` so the helper has fully typed input and output.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +30 to +31
def side_effect(feature=None):
return feature == name
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add explicit type hints for the side_effect parameter and return value so the nested function is fully typed. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The nested side_effect function has neither a parameter type annotation nor a return type annotation.
That is a real typing omission in the new code, so the suggestion is verified.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_impersonation_cache_key.py
**Line:** 30:31
**Comment:**
	*Custom Rule: Add explicit type hints for the `side_effect` parameter and return value so the nested function is fully typed.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +42 to +46

def test_no_per_user_caching_yields_no_key():
database = Database(database_name="d", sqlalchemy_uri="sqlite://")
with override_user(User(username="u")):
assert "impersonation_key" not in _run(database)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add a short docstring to this test function describing the expected behavior being validated. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This test function has no docstring in the final file state.
If the custom rule requires docstrings for new tests, this is a real violation.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_impersonation_cache_key.py
**Line:** 42:46
**Comment:**
	*Custom Rule: Add a short docstring to this test function describing the expected behavior being validated.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎



@patch("superset.utils.cache_keys.feature_flag_manager")
def test_cache_query_by_user_adds_username(feature_flag_mock):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add explicit type annotations for the patched mock argument and the None return type on this new test function. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The patched test function is missing both a type annotation for feature_flag_mock and an explicit -> None return type.
This is a direct mismatch with the suggested typing rule, so the issue is present.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_impersonation_cache_key.py
**Line:** 50:50
**Comment:**
	*Custom Rule: Add explicit type annotations for the patched mock argument and the `None` return type on this new test function.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +86 to +93
def test_per_user_caching_in_extra_json_enables_key():
database = Database(
database_name="d",
sqlalchemy_uri="sqlite://",
extra='{"per_user_caching": true}',
)
with override_user(User(username="alice")):
assert _run(database)["impersonation_key"] == "alice"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add a docstring to this test function so the intent of the scenario is documented consistently with the rule. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The test function does not include a docstring.
Assuming the custom rule requires docstrings for new test scenarios, this is a genuine violation.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_impersonation_cache_key.py
**Line:** 86:93
**Comment:**
	*Custom Rule: Add a docstring to this test function so the intent of the scenario is documented consistently with the rule.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

QUERY_OBJ: dict[str, Any] = {"row_limit": 100, "from_dttm": None, "to_dttm": None}


def _viz_for(database: Database) -> viz.BaseViz:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add a short docstring to this helper function to describe its purpose and expected behavior. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The helper function _viz_for is newly introduced and has no docstring in the existing code.
If the custom rule requires docstrings for new functions, this is a real violation.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/test_viz_cache_key.py
**Line:** 35:35
**Comment:**
	*Custom Rule: Add a short docstring to this helper function to describe its purpose and expected behavior.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

return viz.BaseViz(datasource=datasource, form_data={"viz_type": "table"})


def test_no_per_user_opt_in_keys_match_across_users():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add an explicit return type annotation to this test function (for example, -> None) to comply with the typing rule. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The test function is defined without an explicit return type annotation.
If the rule requires newly added functions to declare -> None, the existing code violates that rule.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/test_viz_cache_key.py
**Line:** 46:46
**Comment:**
	*Custom Rule: Add an explicit return type annotation to this test function (for example, `-> None`) to comply with the typing rule.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

assert key_a != key_b


def test_same_user_same_query_idempotent():
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add a function docstring explaining the scenario this test validates. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This newly added test function has no docstring in the existing code.
Assuming the custom rule is to document new functions, the violation is present.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/test_viz_cache_key.py
**Line:** 83:83
**Comment:**
	*Custom Rule: Add a function docstring explaining the scenario this test validates.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎



@patch("superset.utils.cache_keys.feature_flag_manager")
def test_cache_query_by_user_flag_yields_distinct_keys(feature_flag_mock):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Add explicit type hints for the function parameter and return type to satisfy the typing requirement for new functions. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The function has an untyped parameter (feature_flag_mock) and no return annotation.
If the typing rule applies to new functions here, this is a genuine violation.

Fix in Cursor | Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/test_viz_cache_key.py
**Line:** 96:96
**Comment:**
	*Custom Rule: Add explicit type hints for the function parameter and return type to satisfy the typing requirement for new functions.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 30, 2026

Codecov Report

❌ Patch coverage is 70.00000% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.41%. Comparing base (4244ae8) to head (fc62f22).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
superset/utils/cache_keys.py 69.23% 3 Missing and 1 partial ⚠️
superset/viz.py 60.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #39789      +/-   ##
==========================================
+ Coverage   64.39%   64.41%   +0.02%     
==========================================
  Files        2567     2568       +1     
  Lines      134411   134424      +13     
  Branches    31203    31203              
==========================================
+ Hits        86557    86595      +38     
+ Misses      46354    46332      -22     
+ Partials     1500     1497       -3     
Flag Coverage Δ
hive 39.71% <50.00%> (+<0.01%) ⬆️
mysql 60.01% <70.00%> (?)
postgres 60.09% <70.00%> (+<0.01%) ⬆️
presto 41.46% <60.00%> (+<0.01%) ⬆️
python 61.65% <70.00%> (+0.04%) ⬆️
sqlite 59.73% <70.00%> (+<0.01%) ⬆️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread superset/utils/cache_keys.py
Copy link
Copy Markdown
Member

@sadpandajoe sadpandajoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean bug fix — correctly extracts the per-user cache key logic into a shared helper and applies it to the legacy viz.BaseViz.cache_key() path. Good test coverage for both the helper and the viz integration. LGTM.

Copy link
Copy Markdown
Member

@betodealmeida betodealmeida left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should try to get rid of superset/viz.py, having 2 paths like this is not good.

@Vitor-Avila Vitor-Avila force-pushed the fix/legacy-per-user-caching branch from f41bca7 to fc62f22 Compare April 30, 2026 20:47
@github-actions github-actions Bot removed the api Related to the REST API label Apr 30, 2026
@Vitor-Avila Vitor-Avila merged commit 86eb617 into master Apr 30, 2026
65 checks passed
@Vitor-Avila Vitor-Avila deleted the fix/legacy-per-user-caching branch April 30, 2026 21:04
@bito-code-review
Copy link
Copy Markdown
Contributor

Bito Automatic Review Skipped – PR Already Merged

Bito scheduled an automatic review for this pull request, but the review was skipped because this PR was merged before the review could be run.
No action is needed if you didn't intend to review it. To get a review, you can type /review in a comment and save it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infra:caching Infra setup and configuration related to caching size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants