mirror of
https://github.com/apache/superset.git
synced 2026-04-19 16:14:52 +00:00
[cache warm_up] warm_up slice with dashboard default_filters (#9311)
* [cache warm_up] warm_up slice with dashboard default_filters * update Celery warmup tasks * fix code review comments * add try catch and type checking for parsed dash metadata * extra code review fix
This commit is contained in:
@@ -27,6 +27,7 @@ from superset import app, db, viz
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset.exceptions import SupersetException
|
||||
from superset.legacy import update_time_range
|
||||
from superset.models.dashboard import Dashboard
|
||||
from superset.models.slice import Slice
|
||||
from superset.utils.core import QueryStatus, TimeRangeEndpoint
|
||||
|
||||
@@ -262,3 +263,90 @@ def get_time_range_endpoints(
|
||||
return (TimeRangeEndpoint(start), TimeRangeEndpoint(end))
|
||||
|
||||
return (TimeRangeEndpoint.INCLUSIVE, TimeRangeEndpoint.EXCLUSIVE)
|
||||
|
||||
|
||||
# see all dashboard components type in
|
||||
# /superset-frontend/src/dashboard/util/componentTypes.js
|
||||
CONTAINER_TYPES = ["COLUMN", "GRID", "TABS", "TAB", "ROW"]
|
||||
|
||||
|
||||
def get_dashboard_extra_filters(
|
||||
slice_id: int, dashboard_id: int
|
||||
) -> List[Dict[str, Any]]:
|
||||
session = db.session()
|
||||
dashboard = session.query(Dashboard).filter_by(id=dashboard_id).one_or_none()
|
||||
|
||||
# is chart in this dashboard?
|
||||
if (
|
||||
dashboard is None
|
||||
or not dashboard.json_metadata
|
||||
or not dashboard.slices
|
||||
or not any([slc for slc in dashboard.slices if slc.id == slice_id])
|
||||
):
|
||||
return []
|
||||
|
||||
try:
|
||||
# does this dashboard have default filters?
|
||||
json_metadata = json.loads(dashboard.json_metadata)
|
||||
default_filters = json.loads(json_metadata.get("default_filters", "null"))
|
||||
if not default_filters:
|
||||
return []
|
||||
|
||||
# are default filters applicable to the given slice?
|
||||
filter_scopes = json_metadata.get("filter_scopes", {})
|
||||
layout = json.loads(dashboard.position_json or "{}")
|
||||
|
||||
if (
|
||||
isinstance(layout, dict)
|
||||
and isinstance(filter_scopes, dict)
|
||||
and isinstance(default_filters, dict)
|
||||
):
|
||||
return build_extra_filters(layout, filter_scopes, default_filters, slice_id)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
return []
|
||||
|
||||
|
||||
def build_extra_filters(
|
||||
layout: Dict,
|
||||
filter_scopes: Dict,
|
||||
default_filters: Dict[str, Dict[str, List]],
|
||||
slice_id: int,
|
||||
) -> List[Dict[str, Any]]:
|
||||
extra_filters = []
|
||||
|
||||
# do not apply filters if chart is not in filter's scope or
|
||||
# chart is immune to the filter
|
||||
for filter_id, columns in default_filters.items():
|
||||
scopes_by_filter_field = filter_scopes.get(filter_id, {})
|
||||
for col, val in columns.items():
|
||||
current_field_scopes = scopes_by_filter_field.get(col, {})
|
||||
scoped_container_ids = current_field_scopes.get("scope", ["ROOT_ID"])
|
||||
immune_slice_ids = current_field_scopes.get("immune", [])
|
||||
|
||||
for container_id in scoped_container_ids:
|
||||
if slice_id not in immune_slice_ids and is_slice_in_container(
|
||||
layout, container_id, slice_id
|
||||
):
|
||||
extra_filters.append({"col": col, "op": "in", "val": val})
|
||||
|
||||
return extra_filters
|
||||
|
||||
|
||||
def is_slice_in_container(layout: Dict, container_id: str, slice_id: int) -> bool:
|
||||
if container_id == "ROOT_ID":
|
||||
return True
|
||||
|
||||
node = layout[container_id]
|
||||
node_type = node.get("type")
|
||||
if node_type == "CHART" and node.get("meta", {}).get("chartId") == slice_id:
|
||||
return True
|
||||
|
||||
if node_type in CONTAINER_TYPES:
|
||||
children = node.get("children", [])
|
||||
return any(
|
||||
is_slice_in_container(layout, child_id, slice_id) for child_id in children
|
||||
)
|
||||
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user