mikebridge commented on code in PR #45288:
URL: https://github.com/apache/superset/pull/45288#discussion_r4287679539


##########
tests/unit_tests/semantic_layers/values_endpoint_test.py:
##########
@@ -577,3 +577,139 @@ def 
test_unversioned_suggestion_cache_material_is_unchanged(
         }
         keys.append(cache.get.call_args.args[0])
     assert keys[0] == keys[1]
+
+
[email protected]("use_default", [False, True])
[email protected]("warm", [False, True])
[email protected]("force", [False, True])
[email protected]("search", [False, True])
+def test_disabled_values_cache_skips_reads_and_writes(
+    client: Any,
+    full_api_access: None,
+    semantic_view_datasource: SemanticView,
+    mocker: MockerFixture,
+    use_default: bool,
+    warm: bool,
+    force: bool,
+    search: bool,
+) -> None:
+    """A disabled effective timeout bypasses warm and cold suggestion 
caches."""
+    from flask import current_app
+
+    from superset.constants import CACHE_DISABLED_TIMEOUT
+
+    semantic_view_datasource.cache_timeout = (
+        None if use_default else CACHE_DISABLED_TIMEOUT
+    )
+    mocker.patch.dict(
+        current_app.config,
+        {"CACHE_DEFAULT_TIMEOUT": CACHE_DISABLED_TIMEOUT if use_default else 
300},
+    )
+    cache: MagicMock = 
mocker.patch("superset.datasource.api.cache_manager").data_cache
+    cache.get.return_value = ["stale"] if warm else None
+    response: Any = _get(
+        client,
+        f"category/values/?force={str(force).lower()}" + ("&q=oo" if search 
else ""),
+    )
+
+    assert response.status_code == 200
+    assert response.json["result"] == ["Books", "Clothing"]
+    assert response.headers["X-Cache-Status"] == "MISS"
+    cache.get.assert_not_called()
+    cache.set.assert_not_called()
+    implementation: MagicMock = cast(MagicMock, 
semantic_view_datasource.implementation)
+    implementation.get_values.assert_called_once()
+
+
[email protected]("use_default", [False, True])
[email protected]("warm", [False, True])
+def test_disabled_compatible_cache_skips_reads_and_writes(
+    client: Any,
+    full_api_access: None,
+    semantic_view_datasource: SemanticView,
+    mocker: MockerFixture,
+    use_default: bool,
+    warm: bool,
+) -> None:
+    """A disabled compatibility cache must recompute even with a stored 
result."""
+    from flask import current_app
+
+    from superset.constants import CACHE_DISABLED_TIMEOUT
+
+    semantic_view_datasource.cache_timeout = (
+        None if use_default else CACHE_DISABLED_TIMEOUT
+    )
+    mocker.patch.dict(
+        current_app.config,
+        {"CACHE_DEFAULT_TIMEOUT": CACHE_DISABLED_TIMEOUT if use_default else 
300},
+    )
+    metrics: MagicMock = mocker.patch.object(
+        SemanticView, "get_compatible_metrics", return_value=["revenue"]
+    )
+    dimensions: MagicMock = mocker.patch.object(
+        SemanticView, "get_compatible_dimensions", return_value=["category"]
+    )
+    cache: MagicMock = 
mocker.patch("superset.datasource.api.cache_manager").data_cache
+    cache.get.return_value = {"stale": True} if warm else None
+
+    response: Any = client.post(
+        "/api/v1/datasource/semantic_view/1/compatible", json={}
+    )
+
+    assert response.status_code == 200
+    assert response.json["result"] == {
+        "compatible_metrics": ["revenue"],
+        "compatible_dimensions": ["category"],
+    }
+    metrics.assert_called_once_with([], [])
+    dimensions.assert_called_once_with([], [])
+    cache.get.assert_not_called()
+    cache.set.assert_not_called()
+
+
[email protected]("compatible", [False, True])
[email protected](
+    "datasource_timeout, default_timeout, expected_timeout",
+    [(120, 300, 120), (None, 300, 300), (0, 300, 300), (120, -1, 120)],

Review Comment:
   Added the `(None, 0, 0)` row locally to 
`test_enabled_suggestion_caches_preserve_timeout_and_hits`, for both 
column-values and compatibility. Replacing the sentinel guards with `timeout > 
0` fails both new cases; the other eight enabled-cache cases pass. The final 
endpoint module passes all 89 tests, and hooks/MyPy pass. This is staged with 
the compatibility-key change below and is awaiting independent review before 
push.



##########
superset/datasource/api.py:
##########
@@ -672,7 +678,14 @@ def compatible(self, datasource_type: str, datasource_id: 
int) -> FlaskResponse:
             ).hexdigest()
         )
 
-        if (cached := cache_manager.data_cache.get(cache_key)) is not None:
+        timeout: int = datasource.cache_timeout or app.config.get(

Review Comment:
   I prepared the small key change locally: `compatible:` includes the same 
string form of `changed_on` used by column-values keys. 
`test_compatible_cache_invalidates_after_datasource_edit` first proves an 
unchanged datasource hits its warm entry, then changes its modification time 
and verifies fresh compatibility results. It failed with the old key and passes 
with the new component. The rollout makes previous compatibility entries 
unreachable once, causing a one-time miss; it does not delete them or reclaim 
their storage. Docs and a PR-body update are prepared. Since this changes cache 
identity, I am holding the staged candidate for independent review before 
committing or pushing.



-- 
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