You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ms...@apache.org on 2026/02/10 15:58:11 UTC

(superset) branch msyavuz/fix/refresh-async created (now 0bab66ed5e5)

This is an automated email from the ASF dual-hosted git repository.

msyavuz pushed a change to branch msyavuz/fix/refresh-async
in repository https://gitbox.apache.org/repos/asf/superset.git


      at 0bab66ed5e5 fix(charts): Force refresh skips cache and triggers async job

This branch includes the following new commits:

     new 0bab66ed5e5 fix(charts): Force refresh skips cache and triggers async job

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(superset) 01/01: fix(charts): Force refresh skips cache and triggers async job

Posted by ms...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

msyavuz pushed a commit to branch msyavuz/fix/refresh-async
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 0bab66ed5e55c00fd19734763cb06e76c7ecab34
Author: Mehmet Salih Yavuz <sa...@proton.me>
AuthorDate: Tue Feb 10 18:57:42 2026 +0300

    fix(charts): Force refresh skips cache and triggers async job
---
 superset/charts/data/api.py                      | 20 ++++++-----
 tests/integration_tests/charts/data/api_tests.py | 42 ++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/superset/charts/data/api.py b/superset/charts/data/api.py
index 6166876a36b..cfa84525d73 100644
--- a/superset/charts/data/api.py
+++ b/superset/charts/data/api.py
@@ -351,15 +351,17 @@ class ChartDataRestApi(ChartRestApi):
         """
         Execute command as an async query.
         """
-        # First, look for the chart query results in the cache.
-        with contextlib.suppress(ChartDataCacheLoadError):
-            result = command.run(force_cached=True)
-            if result is not None:
-                # Log is_cached if extra payload callback is provided.
-                # This indicates no async job was triggered - data was already cached
-                # and a synchronous response is being returned immediately.
-                self._log_is_cached(result, add_extra_log_payload)
-                return self._send_chart_response(result)
+        # First, look for the chart query results in the cache,
+        # but only if we're not forcing a refresh.
+        if not form_data.get("force"):
+            with contextlib.suppress(ChartDataCacheLoadError):
+                result = command.run(force_cached=True)
+                if result is not None:
+                    # Log is_cached if extra payload callback is provided.
+                    # This indicates no async job was triggered - data was already
+                    # cached and a synchronous response is being returned immediately.
+                    self._log_is_cached(result, add_extra_log_payload)
+                    return self._send_chart_response(result)
         # Otherwise, kick off a background job to run the chart query.
         # Clients will either poll or be notified of query completion,
         # at which point they will call the /data/<cache_key> endpoint
diff --git a/tests/integration_tests/charts/data/api_tests.py b/tests/integration_tests/charts/data/api_tests.py
index 39241cc47f8..a4c1b95c9e6 100644
--- a/tests/integration_tests/charts/data/api_tests.py
+++ b/tests/integration_tests/charts/data/api_tests.py
@@ -832,6 +832,48 @@ class TestPostChartDataApi(BaseTestChartDataApi):
         # is_cached should be [True] when retrieved from cache
         assert records[0]["is_cached"] == [True]
 
+    @with_feature_flags(GLOBAL_ASYNC_QUERIES=True)
+    @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
+    @mock.patch("superset.charts.data.api.ChartDataCommand.run")
+    def test_chart_data_async_force_refresh(self, mock_run):
+        """
+        Chart data API: Test that force=true skips cache and triggers async job
+        """
+        app._got_first_request = False
+        async_query_manager_factory.init_app(app)
+
+        # Mock the command.run to return cached data
+        class QueryContext:
+            result_format = ChartDataResultFormat.JSON
+            result_type = ChartDataResultType.FULL
+
+        mock_run.return_value = {
+            "query_context": QueryContext(),
+            "queries": [{"query": "select * from foo", "is_cached": True}],
+        }
+
+        # Test without force - should return cached data synchronously
+        self.query_context_payload["result_type"] = ChartDataResultType.FULL
+        rv = self.post_assert_metric(CHART_DATA_URI, self.query_context_payload, "data")
+        assert rv.status_code == 200
+        mock_run.assert_called_once_with(force_cached=True)
+
+        # Reset the mock
+        mock_run.reset_mock()
+
+        # Test with force=true - should skip cache and return async response
+        self.query_context_payload["force"] = True
+        rv = self.post_assert_metric(CHART_DATA_URI, self.query_context_payload, "data")
+        assert rv.status_code == 202
+        # When force=true, command.run should not be called at all in _run_async
+        # since we skip the cache check entirely
+        mock_run.assert_not_called()
+        data = json.loads(rv.data.decode("utf-8"))
+        keys = list(data.keys())
+        self.assertCountEqual(  # noqa: PT009
+            keys, ["channel_id", "job_id", "user_id", "status", "errors", "result_url"]
+        )
+
     @with_feature_flags(GLOBAL_ASYNC_QUERIES=True)
     @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
     def test_chart_data_async_results_type(self):