codeant-ai-for-open-source[bot] commented on code in PR #37516:
URL: https://github.com/apache/superset/pull/37516#discussion_r3595462498


##########
superset/common/utils/query_cache_manager.py:
##########
@@ -192,6 +283,9 @@ def get(
                 query_cache.applied_filter_columns = cache_value.get(
                     "applied_filter_columns", []
                 )
+                query_cache.has_applied_filter_columns = (
+                    "applied_filter_columns" in cache_value
+                )

Review Comment:
   **Suggestion:** Marking legacy cache entries as missing 
`applied_filter_columns` causes them to be treated as cache misses later, but 
this happens after the `force_cached` check has already passed; as a result, 
cache-only requests can silently fall through to live DB execution instead of 
raising a cache-load error. Preserve force-cached semantics by failing fast (or 
raising) when this legacy-miss condition is detected under cache-only mode. 
[api mismatch]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ /api/v1/chart/data/<cache_key> can hit database.
   - ⚠️ Async chart prefetch may execute queries despite cache-only mode.
   - ⚠️ force_cached option no longer guarantees no database execution.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Ensure the DATA cache contains a legacy entry whose value dict lacks the
   "applied_filter_columns" key but does contain "df" and "query" for some 
filtered chart
   query (so `_cache[CacheRegion.DATA].get(key)` returns a truthy `cache_value` 
without that
   key when `QueryCacheManager.get()` is called at
   `superset/common/utils/query_cache_manager.py:253-268`).
   
   2. Call the cache-only chart-data endpoint `GET 
/api/v1/chart/data/<cache_key>`, which is
   implemented by `ChartDataRestApi.data_from_cache` in 
`superset/charts/data/api.py:15-79`;
   this loads the saved form data, builds a `QueryContext`, constructs a 
`ChartDataCommand`,
   and then calls `_get_data_response(command, True)` (line 79), passing 
`force_cached=True`.
   
   3. Inside `_get_data_response`,
   `command.execute(ChartDataExecutionOptions(force_cached=force_cached))` is 
invoked at
   `superset/charts/data/api.py:176-182`, which flows into 
`ChartDataCommand.execute`
   (`superset/commands/chart/data/get_data_command.py:35-47`); there,
   `QueryContext.get_payload_result(cache_query_context=..., force_cached=True,
   materialize=True)` is called (lines 42-46), which delegates to
   `QueryContextProcessor.get_payload_result` and then to `_execute_query_plan`
   (`superset/common/query_context_processor.py:128-136, 468-93`), which 
acquires data via
   `acquire_query_data(..., force_cached=True, ...)` and finally reaches
   `QueryContextProcessor.get_df_payload_result`
   (`superset/common/query_context_processor.py:19-45`).
   
   4. In `get_df_payload_result`, `QueryCacheManager.get` is called with 
`force_cached=True`
   at `superset/common/query_context_processor.py:39-45`; because the legacy 
cache entry
   exists, `QueryCacheManager.get` loads it, sets `query_cache.is_loaded = 
True` and
   `query_cache.has_applied_filter_columns = ("applied_filter_columns" in 
cache_value)`
   (False for legacy entries) at 
`superset/common/utils/query_cache_manager.py:277-288`, and
   does not raise in the `if force_cached and not query_cache.is_loaded` block 
at lines
   325-329. Back in `get_df_payload_result`, the legacy-miss check at
   `superset/common/query_context_processor.py:48-57` sees a non-empty 
`query_obj.filter`,
   `cache.is_loaded` True, and `has_applied_filter_columns` False, so it calls
   `cache.discard_loaded_value()` (line 58), which resets `is_loaded` to False 
in
   `discard_loaded_value` at 
`superset/common/utils/query_cache_manager.py:102-124`. The
   subsequent block `if query_obj and cache_key and not cache.is_loaded:` at
   `superset/common/query_context_processor.py:66-92` then executes
   `self.get_query_result(query_obj)`, issuing a live database query even though
   `force_cached=True`. No `CacheLoadError` is raised anywhere, so 
`ChartDataCommand.execute`
   never converts this into a `ChartDataCacheLoadError` (its `except 
CacheLoadError` at
   `superset/commands/chart/data/get_data_command.py:47-48` is not triggered), 
and
   `ChartDataRestApi.data_from_cache` returns a 200 response backed by a fresh 
DB query
   instead of treating the situation as a cache load failure.
   ```
   </details>
   
   [![Fix in 
Cursor](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-cursor-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=8fbfd18f0372412c8f824013b1f2b788&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 [![Fix in VSCode 
Claude](https://new-codeant-butcket.s3.us-west-1.amazonaws.com/badges/fix-in-vscode-claude-flat.svg)](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=8fbfd18f0372412c8f824013b1f2b788&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/common/utils/query_cache_manager.py
   **Line:** 286:288
   **Comment:**
        *Api Mismatch: Marking legacy cache entries as missing 
`applied_filter_columns` causes them to be treated as cache misses later, but 
this happens after the `force_cached` check has already passed; as a result, 
cache-only requests can silently fall through to live DB execution instead of 
raising a cache-load error. Preserve force-cached semantics by failing fast (or 
raising) when this legacy-miss condition is detected under cache-only mode.
   
   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
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37516&comment_hash=dd8ae0efd8dc80a20913701b55629a917298a18651ce26da4e3d6f8b28f87e0c&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37516&comment_hash=dd8ae0efd8dc80a20913701b55629a917298a18651ce26da4e3d6f8b28f87e0c&reaction=dislike'>👎</a>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to