Skip to content

Commit

Permalink
perf: Memoize the common_bootstrap_payload and include user param (ap…
Browse files Browse the repository at this point in the history
…ache#21018) (apache#21439)

Co-authored-by: Bogdan Kyryliuk <[email protected]>
  • Loading branch information
2 people authored and Rui Zhao committed Sep 13, 2022
1 parent a0e9383 commit 53cc5ea
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 20 deletions.
4 changes: 2 additions & 2 deletions superset/embedded/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import json
from typing import Callable

from flask import abort
from flask import abort, g, request
from flask_appbuilder import expose
from flask_login import AnonymousUserMixin, LoginManager

Expand Down Expand Up @@ -65,7 +65,7 @@ def embedded(
)

bootstrap_data = {
"common": common_bootstrap_payload(),
"common": common_bootstrap_payload(g.user),
"embedded": {
"dashboard_id": embedded.dashboard_id,
},
Expand Down
26 changes: 16 additions & 10 deletions superset/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
SupersetException,
SupersetSecurityException,
)
from superset.extensions import cache_manager
from superset.models.helpers import ImportExportMixin
from superset.models.reports import ReportRecipientType
from superset.superset_typing import FlaskResponse
Expand Down Expand Up @@ -286,7 +287,7 @@ def json_response(obj: Any, status: int = 200) -> FlaskResponse:
def render_app_template(self) -> FlaskResponse:
payload = {
"user": bootstrap_user_data(g.user, include_perms=True),
"common": common_bootstrap_payload(),
"common": common_bootstrap_payload(g.user),
}
return self.render_template(
"superset/spa.html",
Expand All @@ -297,7 +298,7 @@ def render_app_template(self) -> FlaskResponse:
)


def menu_data() -> Dict[str, Any]:
def menu_data(user: User) -> Dict[str, Any]:
menu = appbuilder.menu.get_data()

languages = {}
Expand Down Expand Up @@ -329,22 +330,27 @@ def menu_data() -> Dict[str, Any]:
"build_number": build_number,
"languages": languages,
"show_language_picker": len(languages.keys()) > 1,
"user_is_anonymous": g.user.is_anonymous,
"user_is_anonymous": user.is_anonymous,
"user_info_url": None
if appbuilder.app.config["MENU_HIDE_USER_INFO"]
else appbuilder.get_url_for_userinfo,
"user_logout_url": appbuilder.get_url_for_logout,
"user_login_url": appbuilder.get_url_for_login,
"user_profile_url": None
if g.user.is_anonymous or appbuilder.app.config["MENU_HIDE_USER_INFO"]
else f"/superset/profile/{g.user.username}",
if user.is_anonymous or appbuilder.app.config["MENU_HIDE_USER_INFO"]
else f"/superset/profile/{user.username}",
"locale": session.get("locale", "en"),
},
}


def common_bootstrap_payload() -> Dict[str, Any]:
"""Common data always sent to the client"""
@cache_manager.cache.memoize(timeout=60)
def common_bootstrap_payload(user: User) -> Dict[str, Any]:
"""Common data always sent to the client
The function is memoized as the return value only changes based
on configuration and feature flag values.
"""
messages = get_flashed_messages(with_categories=True)
locale = str(get_locale())

Expand Down Expand Up @@ -377,7 +383,7 @@ def common_bootstrap_payload() -> Dict[str, Any]:
"extra_sequential_color_schemes": conf["EXTRA_SEQUENTIAL_COLOR_SCHEMES"],
"extra_categorical_color_schemes": conf["EXTRA_CATEGORICAL_COLOR_SCHEMES"],
"theme_overrides": conf["THEME_OVERRIDES"],
"menu_data": menu_data(),
"menu_data": menu_data(user),
}
bootstrap_data.update(conf["COMMON_BOOTSTRAP_OVERRIDES_FUNC"](bootstrap_data))
return bootstrap_data
Expand Down Expand Up @@ -488,7 +494,7 @@ def show_unexpected_exception(ex: Exception) -> FlaskResponse:
def get_common_bootstrap_data() -> Dict[str, Any]:
def serialize_bootstrap_data() -> str:
return json.dumps(
{"common": common_bootstrap_payload()},
{"common": common_bootstrap_payload(g.user)},
default=utils.pessimistic_json_iso_dttm_ser,
)

Expand All @@ -506,7 +512,7 @@ class SupersetModelView(ModelView):
def render_app_template(self) -> FlaskResponse:
payload = {
"user": bootstrap_user_data(g.user, include_perms=True),
"common": common_bootstrap_payload(),
"common": common_bootstrap_payload(g.user),
}
return self.render_template(
"superset/spa.html",
Expand Down
12 changes: 6 additions & 6 deletions superset/views/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ def explore(
"force": force,
"user": bootstrap_user_data(g.user, include_perms=True),
"forced_height": request.args.get("height"),
"common": common_bootstrap_payload(),
"common": common_bootstrap_payload(g.user),
}
if slc:
title = slc.slice_name
Expand Down Expand Up @@ -1956,7 +1956,7 @@ def dashboard(

bootstrap_data = {
"user": bootstrap_user_data(g.user, include_perms=True),
"common": common_bootstrap_payload(),
"common": common_bootstrap_payload(g.user),
}

return self.render_template(
Expand Down Expand Up @@ -2674,7 +2674,7 @@ def welcome(self) -> FlaskResponse:

payload = {
"user": bootstrap_user_data(g.user, include_perms=True),
"common": common_bootstrap_payload(),
"common": common_bootstrap_payload(g.user),
}

return self.render_template(
Expand All @@ -2698,7 +2698,7 @@ def profile(self, username: str) -> FlaskResponse:

payload = {
"user": bootstrap_user_data(user, include_perms=True),
"common": common_bootstrap_payload(),
"common": common_bootstrap_payload(g.user),
}

return self.render_template(
Expand Down Expand Up @@ -2762,8 +2762,8 @@ def sqllab(self) -> FlaskResponse:
"""SQL Editor"""
payload = {
"defaultDbId": config["SQLLAB_DEFAULT_DBID"],
"common": common_bootstrap_payload(),
**self._get_sqllab_tabs(g.user.get_id()),
"common": common_bootstrap_payload(g.user),
**self._get_sqllab_tabs(get_user_id()),
}

form_data = request.form.get("form_data")
Expand Down
2 changes: 1 addition & 1 deletion superset/views/dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def embedded(
)

bootstrap_data = {
"common": common_bootstrap_payload(),
"common": common_bootstrap_payload(g.user),
"embedded": {"dashboard_id": dashboard_id_or_slug},
}

Expand Down
4 changes: 3 additions & 1 deletion tests/integration_tests/core_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
from superset.db_engine_specs.base import BaseEngineSpec
from superset.db_engine_specs.mssql import MssqlEngineSpec
from superset.exceptions import SupersetException
from superset.extensions import async_query_manager
from superset.extensions import async_query_manager, cache_manager
from superset.models import core as models
from superset.models.annotations import Annotation, AnnotationLayer
from superset.models.dashboard import Dashboard
Expand Down Expand Up @@ -1400,6 +1400,8 @@ def test_feature_flag_serialization(self):
"""
Functions in feature flags don't break bootstrap data serialization.
"""
# feature flags are cached
cache_manager.cache.clear()
self.login()

encoded = json.dumps(
Expand Down

0 comments on commit 53cc5ea

Please sign in to comment.