This is an automated email from the ASF dual-hosted git repository. maximebeauchemin pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-superset.git
The following commit(s) were added to refs/heads/master by this push: new e95132d [Bugfix/Feature] Fixed slice render staggering on dashboard first load (#3478) e95132d is described below commit e95132ddc3521adf23e5721a7e1bdb93df53c351 Author: Jeff Niu <jeffni...@gmail.com> AuthorDate: Wed Oct 4 10:23:17 2017 -0700 [Bugfix/Feature] Fixed slice render staggering on dashboard first load (#3478) * Feature: disable dashboard refresh staggering * Removed refresh staggering everywhere except during periodic render --- docs/faq.rst | 25 +++++++++-- .../assets/javascripts/dashboard/Dashboard.jsx | 48 +++++++++++----------- .../javascripts/dashboard/components/Controls.jsx | 5 +-- superset/assets/javascripts/modules/superset.js | 4 ++ 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 1c70fc8..cee767a 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -128,8 +128,11 @@ be applied, it's as simple as that. How to limit the timed refresh on a dashboard? ---------------------------------------------- -By default, the dashboard timed refresh feature allows you to automatically requery every slice on a dashboard according to a set schedule. Sometimes, however, you won't want all of the slices to be refreshed - especially if some data is slow moving, or run heavy queries. -To exclude specific slices from the timed refresh process, add the ``timed_refresh_immune_slices`` key to the dashboard ``JSON Metadata`` field: +By default, the dashboard timed refresh feature allows you to automatically re-query every slice +on a dashboard according to a set schedule. Sometimes, however, you won't want all of the slices +to be refreshed - especially if some data is slow moving, or run heavy queries. To exclude specific +slices from the timed refresh process, add the ``timed_refresh_immune_slices`` key to the dashboard +``JSON Metadata`` field: ..code:: @@ -140,8 +143,22 @@ To exclude specific slices from the timed refresh process, add the ``timed_refre "timed_refresh_immune_slices": [324] } -In the example above, if a timed refresh is set for the dashboard, then every slice except 324 will be automatically requeried on schedule. +In the example above, if a timed refresh is set for the dashboard, then every slice except 324 will +be automatically re-queried on schedule. +Slice refresh will also be staggered over the specified period. You can turn off this staggering +by setting the ``stagger_refresh`` to ``false`` and modify the stagger period by setting +``stagger_time`` to a value in milliseconds in the ``JSON Metadata`` field: + +..code:: + + { + "stagger_refresh": false, + "stagger_time": 2500 + } + +Here, the entire dashboard will refresh at once if periodic refresh is on. The stagger time of +2.5 seconds is ignored. Why does fabmanager or superset freezed/hung/not responding when started (my home directory is NFS mounted)? ----------------------------------------------------------------------------------------- @@ -188,7 +205,7 @@ Please note that pretty much any databases that have a SqlAlchemy integration sh How can i configure OAuth authentication and authorization? ----------------------------------------------------------- -You can take a look at this Flask-AppBuilder `configuration example +You can take a look at this Flask-AppBuilder `configuration example <https://github.com/dpgaspar/Flask-AppBuilder/blob/master/examples/oauth/config.py>`_. How can I set a default filter on my dashboard? diff --git a/superset/assets/javascripts/dashboard/Dashboard.jsx b/superset/assets/javascripts/dashboard/Dashboard.jsx index eb471da..5d150a2 100644 --- a/superset/assets/javascripts/dashboard/Dashboard.jsx +++ b/superset/assets/javascripts/dashboard/Dashboard.jsx @@ -126,7 +126,8 @@ export function dashboardContainer(dashboard, datasources, userid) { } }); this.loadPreSelectFilters(); - this.startPeriodicRender(0); + this.renderSlices(this.sliceObjects); + this.firstLoad = false; this.bindResizeToWindowResize(); }, onChange() { @@ -254,25 +255,31 @@ export function dashboardContainer(dashboard, datasources, userid) { this.refreshTimer = null; } }, + renderSlices(slices, force = false, interval = 0) { + if (!interval) { + slices.forEach(slice => slice.render(force)); + return; + } + const meta = this.metadata; + const refreshTime = Math.max(interval, meta.stagger_time || 5000); // default 5 seconds + if (typeof meta.stagger_refresh !== 'boolean') { + meta.stagger_refresh = meta.stagger_refresh === undefined ? + true : meta.stagger_refresh === 'true'; + } + const delay = meta.stagger_refresh ? refreshTime / (slices.length - 1) : 0; + slices.forEach((slice, i) => { + setTimeout(() => slice.render(force), delay * i); + }); + }, startPeriodicRender(interval) { this.stopPeriodicRender(); const dash = this; const immune = this.metadata.timed_refresh_immune_slices || []; - const maxRandomDelay = Math.max(interval * 0.2, 5000); const refreshAll = () => { - dash.sliceObjects.forEach((slice) => { - const force = !dash.firstLoad; - if (immune.indexOf(slice.data.slice_id) === -1) { - setTimeout(() => { - slice.render(force); - }, - // Randomize to prevent all widgets refreshing at the same time - maxRandomDelay * Math.random()); - } - }); - dash.firstLoad = false; + const slices = dash.sliceObjects + .filter(slice => immune.indexOf(slice.data.slice_id) === -1); + dash.renderSlices(slices, true, interval * 0.2); }; - const fetchAndRender = function () { refreshAll(); if (interval > 0) { @@ -285,16 +292,9 @@ export function dashboardContainer(dashboard, datasources, userid) { }, refreshExcept(sliceId) { const immune = this.metadata.filter_immune_slices || []; - this.sliceObjects.forEach((slice) => { - if (slice.data.slice_id !== sliceId && immune.indexOf(slice.data.slice_id) === -1) { - slice.render(); - const sliceSeletor = $(`#${slice.data.slice_id}-cell`); - sliceSeletor.addClass('slice-cell-highlight'); - setTimeout(function () { - sliceSeletor.removeClass('slice-cell-highlight'); - }, 1200); - } - }); + const slices = this.sliceObjects.filter(slice => + slice.data.slice_id !== sliceId && immune.indexOf(slice.data.slice_id) === -1); + this.renderSlices(slices); }, clearFilters(sliceId) { delete this.filters[sliceId]; diff --git a/superset/assets/javascripts/dashboard/components/Controls.jsx b/superset/assets/javascripts/dashboard/components/Controls.jsx index e18c270..5d24055 100644 --- a/superset/assets/javascripts/dashboard/components/Controls.jsx +++ b/superset/assets/javascripts/dashboard/components/Controls.jsx @@ -35,9 +35,8 @@ class Controls extends React.PureComponent { }); } refresh() { - this.props.dashboard.sliceObjects.forEach((slice) => { - slice.render(true); - }); + // Force refresh all slices + this.props.dashboard.renderSlices(this.props.dashboard.sliceObjects, true); } changeCss(css) { this.setState({ css }); diff --git a/superset/assets/javascripts/modules/superset.js b/superset/assets/javascripts/modules/superset.js index a1723eb..6570aba 100644 --- a/superset/assets/javascripts/modules/superset.js +++ b/superset/assets/javascripts/modules/superset.js @@ -65,6 +65,7 @@ const px = function (state) { const container = $(selector); const sliceId = data.slice_id; const formData = applyDefaultFormData(data.form_data); + const sliceCell = $(`#${data.slice_id}-cell`); slice = { data, formData, @@ -114,6 +115,7 @@ const px = function (state) { token.find('img.loading').hide(); container.fadeTo(0.5, 1); + sliceCell.removeClass('slice-cell-highlight'); container.show(); $('.query-and-save button').removeAttr('disabled'); @@ -139,6 +141,7 @@ const px = function (state) { let errorMsg = msg; token.find('img.loading').hide(); container.fadeTo(0.5, 1); + sliceCell.removeClass('slice-cell-highlight'); let errHtml = ''; let o; try { @@ -211,6 +214,7 @@ const px = function (state) { controls.find('a.exportCSV').attr('href', getExploreUrl(formDataExtra, 'csv')); token.find('img.loading').show(); container.fadeTo(0.5, 0.25); + sliceCell.addClass('slice-cell-highlight'); container.css('height', this.height()); $.ajax({ url: this.jsonEndpoint(formDataExtra), -- To stop receiving notification emails like this one, please contact ['"comm...@superset.apache.org" <comm...@superset.apache.org>'].