From 3fd3cd818271b42b5bf1927f2cb411fd8a9a598a Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Thu, 31 Jul 2025 15:36:20 -0500 Subject: [PATCH 01/16] Refactor ClusterHUD router component into ES6 function component --- presto-ui/src/router/ClusterHUD.jsx | 165 ++++++++++++++-------------- 1 file changed, 84 insertions(+), 81 deletions(-) diff --git a/presto-ui/src/router/ClusterHUD.jsx b/presto-ui/src/router/ClusterHUD.jsx index 38bf01e9618bb..db5fae5fb3a4c 100755 --- a/presto-ui/src/router/ClusterHUD.jsx +++ b/presto-ui/src/router/ClusterHUD.jsx @@ -12,7 +12,7 @@ * limitations under the License. */ -import React from "react"; +import React, { useState, useEffect, useRef } from "react"; import { addExponentiallyWeightedToHistory, @@ -32,71 +32,69 @@ const SPARKLINE_PROPERTIES = { disableHiddenCheck: true, }; -export class ClusterHUD extends React.Component { - constructor(props) { - super(props); - this.state = { - runningQueries: [], - queuedQueries: [], - blockedQueries: [], - activeWorkers: [], - runningDrivers: [], - reservedMemory: [], - rowInputRate: [], - byteInputRate: [], - perWorkerCpuTimeRate: [], - clusterCount: [], +export const ClusterHUD = () => { + const [state, setState] = useState({ + runningQueries: [], + queuedQueries: [], + blockedQueries: [], + activeWorkers: [], + runningDrivers: [], + reservedMemory: [], + rowInputRate: [], + byteInputRate: [], + perWorkerCpuTimeRate: [], + clusterCount: [], - lastRender: null, - lastRefresh: null, + lastRender: null, + lastRefresh: null, - lastInputRows: null, - lastInputBytes: null, - lastCpuTime: null, + lastInputRows: null, + lastInputBytes: null, + lastCpuTime: null, - initialized: false, - }; + initialized: false, + }); - this.refreshLoop = this.refreshLoop.bind(this); - } + const timeoutId = useRef(null); - resetTimer() { - clearTimeout(this.timeoutId); + const resetTimer = () => { + clearTimeout(timeoutId.current); // stop refreshing when query finishes or fails - if (this.state.query === null || !this.state.ended) { - this.timeoutId = setTimeout(this.refreshLoop, 1000); + if (state.query === null || !state.ended) { + timeoutId.current = setTimeout(refreshLoop, 1000); } - } + }; - refreshLoop() { - clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously + const refreshLoop = () => { + clearTimeout(timeoutId.current); // to stop multiple series of refreshLoop from going on simultaneously $.get('/v1/cluster', function (clusterState) { let newRowInputRate = []; let newByteInputRate = []; let newPerWorkerCpuTimeRate = []; - if (this.state.lastRefresh !== null) { - const rowsInputSinceRefresh = clusterState.totalInputRows - this.state.lastInputRows; - const bytesInputSinceRefresh = clusterState.totalInputBytes - this.state.lastInputBytes; - const cpuTimeSinceRefresh = clusterState.totalCpuTimeSecs - this.state.lastCpuTime; - const secsSinceRefresh = (Date.now() - this.state.lastRefresh) / 1000.0; + if (state.lastRefresh !== null) { + const rowsInputSinceRefresh = clusterState.totalInputRows - state.lastInputRows; + const bytesInputSinceRefresh = clusterState.totalInputBytes - state.lastInputBytes; + const cpuTimeSinceRefresh = clusterState.totalCpuTimeSecs - state.lastCpuTime; + const secsSinceRefresh = (Date.now() - state.lastRefresh) / 1000.0; - newRowInputRate = addExponentiallyWeightedToHistory(rowsInputSinceRefresh / secsSinceRefresh, this.state.rowInputRate); - newByteInputRate = addExponentiallyWeightedToHistory(bytesInputSinceRefresh / secsSinceRefresh, this.state.byteInputRate); - newPerWorkerCpuTimeRate = addExponentiallyWeightedToHistory((cpuTimeSinceRefresh / clusterState.activeWorkers) / secsSinceRefresh, this.state.perWorkerCpuTimeRate); + newRowInputRate = addExponentiallyWeightedToHistory(rowsInputSinceRefresh / secsSinceRefresh, state.rowInputRate); + newByteInputRate = addExponentiallyWeightedToHistory(bytesInputSinceRefresh / secsSinceRefresh, state.byteInputRate); + newPerWorkerCpuTimeRate = addExponentiallyWeightedToHistory((cpuTimeSinceRefresh / clusterState.activeWorkers) / secsSinceRefresh, state.perWorkerCpuTimeRate); } - this.setState({ + setState({ + ...state, // instantaneous stats - runningQueries: addToHistory(clusterState.runningQueries, this.state.runningQueries), - queuedQueries: addToHistory(clusterState.queuedQueries, this.state.queuedQueries), - blockedQueries: addToHistory(clusterState.blockedQueries, this.state.blockedQueries), - activeWorkers: addToHistory(clusterState.activeWorkers, this.state.activeWorkers), - clusterCount: addToHistory(clusterState.clusterCount, this.state.clusterCount), + runningQueries: addToHistory(clusterState.runningQueries, state.runningQueries), + queuedQueries: addToHistory(clusterState.queuedQueries, state.queuedQueries), + blockedQueries: addToHistory(clusterState.blockedQueries, state.blockedQueries), + activeWorkers: addToHistory(clusterState.activeWorkers, state.activeWorkers), + clusterCount: addToHistory(clusterState.clusterCount, state.clusterCount), // moving averages - runningDrivers: addExponentiallyWeightedToHistory(clusterState.runningDrivers, this.state.runningDrivers), - reservedMemory: addExponentiallyWeightedToHistory(clusterState.reservedMemory, this.state.reservedMemory), + runningDrivers: addExponentiallyWeightedToHistory(clusterState.runningDrivers, state.runningDrivers), + reservedMemory: addExponentiallyWeightedToHistory(clusterState.reservedMemory, state.reservedMemory), // moving averages for diffs rowInputRate: newRowInputRate, @@ -111,45 +109,50 @@ export class ClusterHUD extends React.Component { lastRefresh: Date.now() }); - this.resetTimer(); - }.bind(this)) + resetTimer(); + }) .fail(function () { - this.resetTimer(); - }.bind(this)); - } + resetTimer(); + }); + }; - componentDidMount() { - this.refreshLoop(); - } + useEffect(() => { + refreshLoop(); + + return () => { + clearTimeout(timeoutId.current); + }; + }, []); - componentDidUpdate() { + useEffect(() => { // prevent multiple calls to componentDidUpdate (resulting from calls to setState or otherwise) within the refresh interval from re-rendering sparklines/charts - if (this.state.lastRender === null || (Date.now() - this.state.lastRender) >= 1000) { + if (state.lastRender === null || (Date.now() - state.lastRender) >= 1000) { const renderTimestamp = Date.now(); - $('#running-queries-sparkline').sparkline(this.state.runningQueries, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); - $('#blocked-queries-sparkline').sparkline(this.state.blockedQueries, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); - $('#queued-queries-sparkline').sparkline(this.state.queuedQueries, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); + $('#running-queries-sparkline').sparkline(state.runningQueries, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); + $('#blocked-queries-sparkline').sparkline(state.blockedQueries, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); + $('#queued-queries-sparkline').sparkline(state.queuedQueries, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); - $('#active-workers-sparkline').sparkline(this.state.activeWorkers, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); - $('#cluster-count-sparkline').sparkline(this.state.clusterCount, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); + $('#active-workers-sparkline').sparkline(state.activeWorkers, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); + $('#cluster-count-sparkline').sparkline(state.clusterCount, $.extend({}, SPARKLINE_PROPERTIES, {chartRangeMin: 0})); - $('#running-drivers-sparkline').sparkline(this.state.runningDrivers, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: precisionRound})); - $('#reserved-memory-sparkline').sparkline(this.state.reservedMemory, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: formatDataSizeBytes})); + $('#running-drivers-sparkline').sparkline(state.runningDrivers, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: precisionRound})); + $('#reserved-memory-sparkline').sparkline(state.reservedMemory, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: formatDataSizeBytes})); - $('#row-input-rate-sparkline').sparkline(this.state.rowInputRate, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: formatCount})); - $('#byte-input-rate-sparkline').sparkline(this.state.byteInputRate, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: formatDataSizeBytes})); - $('#cpu-time-rate-sparkline').sparkline(this.state.perWorkerCpuTimeRate, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: precisionRound})); + $('#row-input-rate-sparkline').sparkline(state.rowInputRate, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: formatCount})); + $('#byte-input-rate-sparkline').sparkline(state.byteInputRate, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: formatDataSizeBytes})); + $('#cpu-time-rate-sparkline').sparkline(state.perWorkerCpuTimeRate, $.extend({}, SPARKLINE_PROPERTIES, {numberFormatter: precisionRound})); - this.setState({ + setState(prevState => ({ + ...prevState, lastRender: renderTimestamp - }); + })); } - $('[data-bs-toggle="tooltip"]')?.tooltip?.(); - } + $('[data-bs-toggle="tooltip"]').tooltip(); + }); - render() { - return (
+ return ( +
@@ -171,7 +174,7 @@ export class ClusterHUD extends React.Component {
- {this.state.runningQueries[this.state.runningQueries.length - 1]} + {state.runningQueries[state.runningQueries.length - 1]}
Loading ...
@@ -179,7 +182,7 @@ export class ClusterHUD extends React.Component {
- {this.state.clusterCount[this.state.clusterCount.length - 1]} + {state.clusterCount[state.clusterCount.length - 1]}
Loading ...
@@ -205,7 +208,7 @@ export class ClusterHUD extends React.Component {
- {this.state.queuedQueries[this.state.queuedQueries.length - 1]} + {state.queuedQueries[state.queuedQueries.length - 1]}
Loading ...
@@ -213,7 +216,7 @@ export class ClusterHUD extends React.Component {
- {this.state.activeWorkers[this.state.activeWorkers.length - 1]} + {state.activeWorkers[state.activeWorkers.length - 1]}
Loading ...
@@ -240,7 +243,7 @@ export class ClusterHUD extends React.Component {
- {this.state.blockedQueries[this.state.blockedQueries.length - 1]} + {state.blockedQueries[state.blockedQueries.length - 1]}
Loading ...
@@ -248,13 +251,13 @@ export class ClusterHUD extends React.Component {
- {formatCount(this.state.runningDrivers[this.state.runningDrivers.length - 1])} + {formatCount(state.runningDrivers[state.runningDrivers.length - 1])}
Loading ...
-
); - } +
+ ); } From b629667b42fcd00d88a61bce621c4f340fef4dd8 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Thu, 31 Jul 2025 15:37:01 -0500 Subject: [PATCH 02/16] Refactor PageTitle router component to ES6 function component --- presto-ui/src/router/PageTitle.jsx | 196 ++++++++++++++--------------- 1 file changed, 92 insertions(+), 104 deletions(-) diff --git a/presto-ui/src/router/PageTitle.jsx b/presto-ui/src/router/PageTitle.jsx index e35938a9b19a0..b45fc59139419 100755 --- a/presto-ui/src/router/PageTitle.jsx +++ b/presto-ui/src/router/PageTitle.jsx @@ -12,42 +12,27 @@ * limitations under the License. */ //@flow -import React from "react"; +import React, { useState, useEffect, useRef } from "react"; -type Props = { - title: string -} +export const PageTitle = (props) => { + const [state, setState] = useState({ + noConnection: false, + lightShown: false, + info: null, + lastSuccess: Date.now(), + modalShown: false, + errorText: null, + }); -type State = { - noConnection: boolean, - lightShown: boolean, - info: ?any, - lastSuccess: number, - modalShown: boolean, - errorText: ?string, -} + const timeoutId = useRef(null); -export class PageTitle extends React.Component { - timeoutId: TimeoutID; - - constructor(props: Props) { - super(props); - this.state = { - noConnection: false, - lightShown: false, - info: null, - lastSuccess: Date.now(), - modalShown: false, - errorText: null, - }; - } - - refreshLoop: () => void = () => { - clearTimeout(this.timeoutId); + const refreshLoop = () => { + clearTimeout(timeoutId.current); fetch("/v1/info") .then(response => response.json()) .then(info => { - this.setState({ + setState({ + ...state, info: info, noConnection: false, lastSuccess: Date.now(), @@ -55,36 +40,41 @@ export class PageTitle extends React.Component { }); //$FlowFixMe$ Bootstrap 3 plugin $('#no-connection-modal').hide(); - this.resetTimer(); + resetTimer(); }) .catch(error => { - this.setState({ + setState(prevState => ({ + ...prevState, noConnection: true, - lightShown: !this.state.lightShown, + lightShown: !prevState.lightShown, errorText: error - }); - this.resetTimer(); + })); + resetTimer(); - if (!this.state.modalShown && (error || (Date.now() - this.state.lastSuccess) > 30 * 1000)) { + if (!state.modalShown && (error || (Date.now() - state.lastSuccess) > 30 * 1000)) { //$FlowFixMe$ Bootstrap 3 plugin $('#no-connection-modal').hide(); - this.setState({modalShown: true}); + setState(prevState => ({...prevState, modalShown: true})); } }); - } + }; - resetTimer() { - clearTimeout(this.timeoutId); - this.timeoutId = setTimeout(this.refreshLoop.bind(this), 1000); - } + const resetTimer = () => { + clearTimeout(timeoutId.current); + timeoutId.current = setTimeout(refreshLoop, 1000); + }; - componentDidMount() { - this.refreshLoop.bind(this)(); - } + useEffect(() => { + refreshLoop(); + + return () => { + clearTimeout(timeoutId.current); + }; + }, []); - renderStatusLight(): any { - if (this.state.noConnection) { - if (this.state.lightShown) { + const renderStatusLight = () => { + if (state.noConnection) { + if (state.lightShown) { return ; } else { @@ -92,67 +82,65 @@ export class PageTitle extends React.Component { } } return ; - } + }; - render(): any { - const info = this.state.info; - if (!info) { - return null; - } + const info = state.info; + if (!info) { + return null; + } - return ( -
- + - ); - } -} +
+ ); +}; From c8c9d20c9cb6681463528723c871021e050f920d Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Thu, 31 Jul 2025 15:37:24 -0500 Subject: [PATCH 03/16] Refactor QueryList and sub-components into ES6 function components --- presto-ui/src/router/QueryList.jsx | 750 ++++++++++++++--------------- 1 file changed, 355 insertions(+), 395 deletions(-) diff --git a/presto-ui/src/router/QueryList.jsx b/presto-ui/src/router/QueryList.jsx index dafa1ae27887d..96b1e7d6bb39a 100755 --- a/presto-ui/src/router/QueryList.jsx +++ b/presto-ui/src/router/QueryList.jsx @@ -12,7 +12,7 @@ * limitations under the License. */ -import React from "react"; +import React, { useState, useEffect, useRef } from "react"; import { formatDataSizeBytes, @@ -28,220 +28,173 @@ import { truncateString } from "../utils"; -export class QueryListItem extends React.Component { - static stripQueryTextWhitespace(queryText) { - const lines = queryText.split("\n"); - let minLeadingWhitespace = -1; - for (let i = 0; i < lines.length; i++) { - if (minLeadingWhitespace === 0) { - break; - } +const stripQueryTextWhitespace = (queryText) => { + const lines = queryText.split("\n"); + let minLeadingWhitespace = -1; + for (let i = 0; i < lines.length; i++) { + if (minLeadingWhitespace === 0) { + break; + } - if (lines[i].trim().length === 0) { - continue; - } + if (lines[i].trim().length === 0) { + continue; + } - const leadingWhitespace = lines[i].search(/\S/); + const leadingWhitespace = lines[i].search(/\S/); - if (leadingWhitespace > -1 && ((leadingWhitespace < minLeadingWhitespace) || minLeadingWhitespace === -1)) { - minLeadingWhitespace = leadingWhitespace; - } + if (leadingWhitespace > -1 && ((leadingWhitespace < minLeadingWhitespace) || minLeadingWhitespace === -1)) { + minLeadingWhitespace = leadingWhitespace; } + } - let formattedQueryText = ""; + let formattedQueryText = ""; - for (let i = 0; i < lines.length; i++) { - const trimmedLine = lines[i].substring(minLeadingWhitespace).replace(/\s+$/g, ''); + for (let i = 0; i < lines.length; i++) { + const trimmedLine = lines[i].substring(minLeadingWhitespace).replace(/\s+$/g, ''); - if (trimmedLine.length > 0) { - formattedQueryText += trimmedLine; + if (trimmedLine.length > 0) { + formattedQueryText += trimmedLine; - if (i < (lines.length - 1)) { - formattedQueryText += "\n"; - } + if (i < (lines.length - 1)) { + formattedQueryText += "\n"; } } - - return truncateString(formattedQueryText, 300); } - render() { - const query = this.props.query; - const progressBarStyle = {width: getProgressBarPercentage(query) + "%", backgroundColor: getQueryStateColor(query)}; - - const driverDetails = ( -
- -    - {formatCount(query.progress.completedDrivers)} - - -    - {(query.queryState === "FINISHED" || query.queryState === "FAILED") ? 0 : query.progress.runningDrivers} - - -    - {(query.queryState === "FINISHED" || query.queryState === "FAILED") ? 0 : query.progress.queuedDrivers} - -
); - - const newDriverDetails = ( -
- -    - {formatCount(query.progress.completedNewDrivers)} - - -    - {(query.queryState === "FINISHED" || query.queryState === "FAILED") ? 0 : query.progress.runningNewDrivers} - - -    - {(query.queryState === "FINISHED" || query.queryState === "FAILED") ? 0 : query.progress.queuedNewDrivers} - -
); - - const splitDetails = ( -
- -    - {formatCount(query.progress.completedSplits)} - - -    - {(query.queryState === "FINISHED" || query.queryState === "FAILED") ? 0 : query.progress.runningSplits} - - -    - {(query.queryState === "FINISHED" || query.queryState === "FAILED") ? 0 : query.progress.queuedSplits} - -
); - - const timingDetails = ( -
- -    - {query.queryStats.executionTime} - - -    - {query.queryStats.elapsedTime} - - -    - {query.queryStats.totalCpuTime} - -
); + return truncateString(formattedQueryText, 300); +} - const memoryDetails = ( -
- -    - {query.queryStats.totalMemoryReservation} - - -    - {query.queryStats.peakTotalMemoryReservation} +export const QueryListItem = (props) => { + const query = props.query; + const progressBarStyle = {width: getProgressBarPercentage(query) + "%", backgroundColor: getQueryStateColor(query)}; + + const splitDetails = ( +
+ +    + {query.queryStats.completedDrivers} + + +    + {(query.state === "FINISHED" || query.state === "FAILED") ? 0 : query.queryStats.runningDrivers} + + +    + {(query.state === "FINISHED" || query.state === "FAILED") ? 0 : query.queryStats.queuedDrivers} - -    - {formatDataSizeBytes(query.queryStats.cumulativeUserMemory / 1000.0)} - -
); - - let user = ({query.session.user}); - if (query.session.principal) { - user = ( - {query.session.user} - ); - } +
); + + const timingDetails = ( +
+ +    + {query.queryStats.executionTime} + + +    + {query.queryStats.elapsedTime} + + +    + {query.queryStats.totalCpuTime} + +
); + + const memoryDetails = ( +
+ +    + {query.queryStats.totalMemoryReservation} + + +    + {query.queryStats.peakTotalMemoryReservation} + + +    + {formatDataSizeBytes(query.queryStats.cumulativeUserMemory / 1000.0)} + +
); + + let user = ({query.session.user}); + if (query.session.principal) { + user = ( + {query.session.user} + ); + } - return ( -
-
-
-
- -
- {formatShortTime(new Date(Date.parse(query.queryStats.createTime)))} -
-
-
-
- -    - {truncateString(user, 35)} - -
+ return ( +
+
+
+
+ -
-
- -    - {truncateString(query.session.source, 35)} - -
+
+ {formatShortTime(new Date(Date.parse(query.queryStats.createTime)))}
- - { query.queryStats.completedSplits ? - <> -
- {newDriverDetails} -
-
- {splitDetails} -
- : -
- {driverDetails} -
- } -
- {timingDetails} +
+
+
+ +    + {truncateString(user, 35)} +
-
- {memoryDetails} +
+
+
+ +    + {truncateString(query.session.source, 35)} +
-
-
-
-
-
- {getProgressBarTitle(query)} -
+
+ {splitDetails} +
+
+ {timingDetails} +
+
+ {memoryDetails} +
+
+
+
+
+
+
+ {getProgressBarTitle(query)}
-
-
-
{QueryListItem.stripQueryTextWhitespace(query.query)}
-
+
+
+
+
{stripQueryTextWhitespace(query.query)}
- ); - } -} +
+ ); +}; -class DisplayedQueriesList extends React.Component { - render() { - const queryNodes = this.props.queries.map(function (query) { - return ( - - ); - }.bind(this)); +const DisplayedQueriesList = (props) => { + const queryNodes = props.queries.map(function (query) { return ( -
- {queryNodes} -
+ ); - } -} + }); + return ( +
+ {queryNodes} +
+ ); +}; const FILTER_TYPE = { RUNNING: function (query) { @@ -272,41 +225,36 @@ const SORT_ORDER = { DESCENDING: function (value) {return -value} }; -export class QueryList extends React.Component { - constructor(props) { - super(props); - this.state = { - allQueries: [], - displayedQueries: [], - reorderInterval: 5000, - currentSortType: SORT_TYPE.CREATED, - currentSortOrder: SORT_ORDER.DESCENDING, - stateFilters: [FILTER_TYPE.RUNNING, FILTER_TYPE.QUEUED], - errorTypeFilters: [ERROR_TYPE.INTERNAL_ERROR, ERROR_TYPE.INSUFFICIENT_RESOURCES, ERROR_TYPE.EXTERNAL], - searchString: '', - maxQueries: 100, - lastRefresh: Date.now(), - lastReorder: Date.now(), - initialized: false - }; - - this.refreshLoop = this.refreshLoop.bind(this); - this.handleSearchStringChange = this.handleSearchStringChange.bind(this); - this.executeSearch = this.executeSearch.bind(this); - this.handleSortClick = this.handleSortClick.bind(this); - } - - sortAndLimitQueries(queries, sortType, sortOrder, maxQueries) { +export const QueryList = (props) => { + const [state, setState] = useState({ + allQueries: [], + displayedQueries: [], + reorderInterval: 5000, + currentSortType: SORT_TYPE.CREATED, + currentSortOrder: SORT_ORDER.DESCENDING, + stateFilters: [FILTER_TYPE.RUNNING, FILTER_TYPE.QUEUED], + errorTypeFilters: [ERROR_TYPE.INTERNAL_ERROR, ERROR_TYPE.INSUFFICIENT_RESOURCES, ERROR_TYPE.EXTERNAL], + searchString: '', + maxQueries: 100, + lastRefresh: Date.now(), + lastReorder: Date.now(), + initialized: false + }); + + const timeoutId = useRef(null); + const searchTimeoutId = useRef(null); + + const sortAndLimitQueries = (queries, sortType, sortOrder, maxQueries) => { queries.sort(function (queryA, queryB) { return sortOrder(sortType(queryA) - sortType(queryB)); - }, this); + }); if (maxQueries !== 0 && queries.length > maxQueries) { queries.splice(maxQueries, (queries.length - maxQueries)); } - } + }; - filterQueries(queries, stateFilters, errorTypeFilters, searchString) { + const filterQueries = (queries, stateFilters, errorTypeFilters, searchString) => { const stateFilteredQueries = queries.filter(function (query) { for (let i = 0; i < stateFilters.length; i++) { if (stateFilters[i](query)) { @@ -345,21 +293,21 @@ export class QueryList extends React.Component { return true; } - }, this); + }); } - } + }; - resetTimer() { - clearTimeout(this.timeoutId); + const resetTimer = () => { + clearTimeout(timeoutId.current); // stop refreshing when query finishes or fails - if (this.state.query === null || !this.state.ended) { - this.timeoutId = setTimeout(this.refreshLoop, 1000); + if (state.query === null || !state.ended) { + timeoutId.current = setTimeout(refreshLoop, 1000); } - } + }; - refreshLoop() { - clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously - clearTimeout(this.searchTimeoutId); + const refreshLoop = () => { + clearTimeout(timeoutId.current); // to stop multiple series of refreshLoop from going on simultaneously + clearTimeout(searchTimeoutId.current); $.get('/v1/query', function (queryList) { const queryMap = queryList.reduce(function (map, query) { @@ -368,7 +316,7 @@ export class QueryList extends React.Component { }, {}); let updatedQueries = []; - this.state.displayedQueries.forEach(function (oldQuery) { + state.displayedQueries.forEach(function (oldQuery) { if (oldQuery.queryId in queryMap) { updatedQueries.push(queryMap[oldQuery.queryId]); queryMap[oldQuery.queryId] = false; @@ -381,107 +329,118 @@ export class QueryList extends React.Component { newQueries.push(queryMap[queryId]); } } - newQueries = this.filterQueries(newQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); + newQueries = filterQueries(newQueries, state.stateFilters, state.errorTypeFilters, state.searchString); const lastRefresh = Date.now(); - let lastReorder = this.state.lastReorder; + let lastReorder = state.lastReorder; - if (this.state.reorderInterval !== 0 && ((lastRefresh - lastReorder) >= this.state.reorderInterval)) { - updatedQueries = this.filterQueries(updatedQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); + if (state.reorderInterval !== 0 && ((lastRefresh - lastReorder) >= state.reorderInterval)) { + updatedQueries = filterQueries(updatedQueries, state.stateFilters, state.errorTypeFilters, state.searchString); updatedQueries = updatedQueries.concat(newQueries); - this.sortAndLimitQueries(updatedQueries, this.state.currentSortType, this.state.currentSortOrder, 0); + sortAndLimitQueries(updatedQueries, state.currentSortType, state.currentSortOrder, 0); lastReorder = Date.now(); } else { - this.sortAndLimitQueries(newQueries, this.state.currentSortType, this.state.currentSortOrder, 0); + sortAndLimitQueries(newQueries, state.currentSortType, state.currentSortOrder, 0); updatedQueries = updatedQueries.concat(newQueries); } - if (this.state.maxQueries !== 0 && (updatedQueries.length > this.state.maxQueries)) { - updatedQueries.splice(this.state.maxQueries, (updatedQueries.length - this.state.maxQueries)); + if (state.maxQueries !== 0 && (updatedQueries.length > state.maxQueries)) { + updatedQueries.splice(state.maxQueries, (updatedQueries.length - state.maxQueries)); } - this.setState({ + setState({ + ...state, allQueries: queryList, displayedQueries: updatedQueries, lastRefresh: lastRefresh, lastReorder: lastReorder, initialized: true }); - this.resetTimer(); - }.bind(this)) + resetTimer(); + }) .fail(function () { - this.setState({ + setState(prevState => ({ + ...prevState, initialized: true, - }); - this.resetTimer(); - }.bind(this)); - } - - componentDidMount() { - this.refreshLoop(); - } + })); + resetTimer(); + }); + }; + + useEffect(() => { + refreshLoop(); + + return () => { + clearTimeout(timeoutId.current); + clearTimeout(searchTimeoutId.current); + }; + }, []); - handleSearchStringChange(event) { + const handleSearchStringChange = (event) => { const newSearchString = event.target.value; - clearTimeout(this.searchTimeoutId); + clearTimeout(searchTimeoutId.current); - this.setState({ + setState({ + ...state, searchString: newSearchString }); - this.searchTimeoutId = setTimeout(this.executeSearch, 200); - } + searchTimeoutId.current = setTimeout(executeSearch, 200); + }; - executeSearch() { - clearTimeout(this.searchTimeoutId); + const executeSearch = () => { + clearTimeout(searchTimeoutId.current); - const newDisplayedQueries = this.filterQueries(this.state.allQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); - this.sortAndLimitQueries(newDisplayedQueries, this.state.currentSortType, this.state.currentSortOrder, this.state.maxQueries); + const newDisplayedQueries = filterQueries(state.allQueries, state.stateFilters, state.errorTypeFilters, state.searchString); + sortAndLimitQueries(newDisplayedQueries, state.currentSortType, state.currentSortOrder, state.maxQueries); - this.setState({ + setState({ + ...state, displayedQueries: newDisplayedQueries }); - } + }; - renderMaxQueriesListItem(maxQueries, maxQueriesText) { + const renderMaxQueriesListItem = (maxQueries, maxQueriesText) => { return ( -
  • {maxQueriesText} +
  • {maxQueriesText}
  • ); - } + }; - handleMaxQueriesClick(newMaxQueries) { - const filteredQueries = this.filterQueries(this.state.allQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); - this.sortAndLimitQueries(filteredQueries, this.state.currentSortType, this.state.currentSortOrder, newMaxQueries); + const handleMaxQueriesClick = (newMaxQueries) => { + const filteredQueries = filterQueries(state.allQueries, state.stateFilters, state.errorTypeFilters, state.searchString); + sortAndLimitQueries(filteredQueries, state.currentSortType, state.currentSortOrder, newMaxQueries); - this.setState({ + setState({ + ...state, maxQueries: newMaxQueries, displayedQueries: filteredQueries }); - } + }; - renderReorderListItem(interval, intervalText) { + const renderReorderListItem = (interval, intervalText) => { return ( -
  • {intervalText}
  • +
  • {intervalText}
  • ); - } + }; - handleReorderClick(interval) { - if (this.state.reorderInterval !== interval) { - this.setState({ + const handleReorderClick = (interval) => { + if (state.reorderInterval !== interval) { + setState({ + ...state, reorderInterval: interval, }); } - } + }; - renderSortListItem(sortType, sortText) { - if (this.state.currentSortType === sortType) { - const directionArrow = this.state.currentSortOrder === SORT_ORDER.ASCENDING ? : + const renderSortListItem = (sortType, sortText) => { + if (state.currentSortType === sortType) { + const directionArrow = state.currentSortOrder === SORT_ORDER.ASCENDING ? : ; return (
  • - + {sortText} {directionArrow}
  • ); @@ -489,190 +448,191 @@ export class QueryList extends React.Component { else { return (
  • - - {sortText} + + {sortText}
  • ); } - } + }; - handleSortClick(sortType) { + const handleSortClick = (sortType) => { const newSortType = sortType; let newSortOrder = SORT_ORDER.DESCENDING; - if (this.state.currentSortType === sortType && this.state.currentSortOrder === SORT_ORDER.DESCENDING) { + if (state.currentSortType === sortType && state.currentSortOrder === SORT_ORDER.DESCENDING) { newSortOrder = SORT_ORDER.ASCENDING; } - const newDisplayedQueries = this.filterQueries(this.state.allQueries, this.state.stateFilters, this.state.errorTypeFilters, this.state.searchString); - this.sortAndLimitQueries(newDisplayedQueries, newSortType, newSortOrder, this.state.maxQueries); + const newDisplayedQueries = filterQueries(state.allQueries, state.stateFilters, state.errorTypeFilters, state.searchString); + sortAndLimitQueries(newDisplayedQueries, newSortType, newSortOrder, state.maxQueries); - this.setState({ + setState({ + ...state, displayedQueries: newDisplayedQueries, currentSortType: newSortType, currentSortOrder: newSortOrder }); - } + }; - renderFilterButton(filterType, filterText) { + const renderFilterButton = (filterType, filterText) => { let checkmarkStyle = {color: '#57aac7'}; let classNames = "btn btn-sm btn-info style-check rounded-0"; - if (this.state.stateFilters.indexOf(filterType) > -1) { + if (state.stateFilters.indexOf(filterType) > -1) { classNames += " active"; checkmarkStyle = {color: '#ffffff'}; } return ( - ); - } + }; - handleStateFilterClick(filter) { - const newFilters = this.state.stateFilters.slice(); - if (this.state.stateFilters.indexOf(filter) > -1) { + const handleStateFilterClick = (filter) => { + const newFilters = state.stateFilters.slice(); + if (state.stateFilters.indexOf(filter) > -1) { newFilters.splice(newFilters.indexOf(filter), 1); } else { newFilters.push(filter); } - const filteredQueries = this.filterQueries(this.state.allQueries, newFilters, this.state.errorTypeFilters, this.state.searchString); - this.sortAndLimitQueries(filteredQueries, this.state.currentSortType, this.state.currentSortOrder); + const filteredQueries = filterQueries(state.allQueries, newFilters, state.errorTypeFilters, state.searchString); + sortAndLimitQueries(filteredQueries, state.currentSortType, state.currentSortOrder); - this.setState({ + setState({ + ...state, stateFilters: newFilters, displayedQueries: filteredQueries }); - } + }; - renderErrorTypeListItem(errorType, errorTypeText) { + const renderErrorTypeListItem = (errorType, errorTypeText) => { let checkmarkStyle = {color: '#ffffff'}; - if (this.state.errorTypeFilters.indexOf(errorType) > -1) { + if (state.errorTypeFilters.indexOf(errorType) > -1) { checkmarkStyle = {color: 'black'}; } return (
  • - +  {errorTypeText}
  • ); - } + }; - handleErrorTypeFilterClick(errorType) { - const newFilters = this.state.errorTypeFilters.slice(); - if (this.state.errorTypeFilters.indexOf(errorType) > -1) { + const handleErrorTypeFilterClick = (errorType) => { + const newFilters = state.errorTypeFilters.slice(); + if (state.errorTypeFilters.indexOf(errorType) > -1) { newFilters.splice(newFilters.indexOf(errorType), 1); } else { newFilters.push(errorType); } - const filteredQueries = this.filterQueries(this.state.allQueries, this.state.stateFilters, newFilters, this.state.searchString); - this.sortAndLimitQueries(filteredQueries, this.state.currentSortType, this.state.currentSortOrder); + const filteredQueries = filterQueries(state.allQueries, state.stateFilters, newFilters, state.searchString); + sortAndLimitQueries(filteredQueries, state.currentSortType, state.currentSortOrder); - this.setState({ + setState({ + ...state, errorTypeFilters: newFilters, displayedQueries: filteredQueries }); - } - - render() { - let queryList = ; - if (this.state.displayedQueries === null || this.state.displayedQueries.length === 0) { - let label = (
    Loading...
    ); - if (this.state.initialized) { - if (this.state.allQueries === null || this.state.allQueries.length === 0) { - label = "No queries"; - } - else { - label = "No queries matched filters"; - } + }; + + let queryList = ; + if (state.displayedQueries === null || state.displayedQueries.length === 0) { + let label = (
    Loading...
    ); + if (state.initialized) { + if (state.allQueries === null || state.allQueries.length === 0) { + label = "No queries"; + } + else { + label = "No queries matched filters"; } - queryList = ( -
    -
    {label}
    -
    - ); } + queryList = ( +
    +
    {label}
    +
    + ); + } - return ( -
    -
    -
    + return ( +
    +
    +
    + +
    + +
    - State: - onChange={this.handleSearchStringChange} value={this.state.searchString} style={{backgroundColor: "white", flex:"0 1 500.586px", width:"500.586px" ,color: 'black', fontSize: '12px', borderColor:"#CCCCCC"}} /> -
    -
    - State: - -
    -
    - {this.renderFilterButton(FILTER_TYPE.RUNNING, "Running")} - {this.renderFilterButton(FILTER_TYPE.QUEUED, "Queued")} - {this.renderFilterButton(FILTER_TYPE.FINISHED, "Finished")} - -
      - {this.renderErrorTypeListItem(ERROR_TYPE.INTERNAL_ERROR, "Internal Error")} - {this.renderErrorTypeListItem(ERROR_TYPE.EXTERNAL, "External Error")} - {this.renderErrorTypeListItem(ERROR_TYPE.INSUFFICIENT_RESOURCES, "Resources Error")} - {this.renderErrorTypeListItem(ERROR_TYPE.USER_ERROR, "User Error")} -
    - -
    -   -
    - -
      - {this.renderSortListItem(SORT_TYPE.CREATED, "Creation Time")} - {this.renderSortListItem(SORT_TYPE.ELAPSED, "Elapsed Time")} - {this.renderSortListItem(SORT_TYPE.CPU, "CPU Time")} - {this.renderSortListItem(SORT_TYPE.EXECUTION, "Execution Time")} - {this.renderSortListItem(SORT_TYPE.CURRENT_MEMORY, "Current Memory")} - {this.renderSortListItem(SORT_TYPE.CUMULATIVE_MEMORY, "Cumulative User Memory")} -
    -
    -   -
    - -
      - {this.renderReorderListItem(1000, "1s")} - {this.renderReorderListItem(5000, "5s")} - {this.renderReorderListItem(10000, "10s")} - {this.renderReorderListItem(30000, "30s")} -
      - {this.renderReorderListItem(0, "Off")} -
    -
    -   -
    - -
      - {this.renderMaxQueriesListItem(20, "20 queries")} - {this.renderMaxQueriesListItem(50, "50 queries")} - {this.renderMaxQueriesListItem(100, "100 queries")} -
      - {this.renderMaxQueriesListItem(0, "All queries")} -
    -
    +
    +
    + {renderFilterButton(FILTER_TYPE.RUNNING, "Running")} + {renderFilterButton(FILTER_TYPE.QUEUED, "Queued")} + {renderFilterButton(FILTER_TYPE.FINISHED, "Finished")} + +
      + {renderErrorTypeListItem(ERROR_TYPE.INTERNAL_ERROR, "Internal Error")} + {renderErrorTypeListItem(ERROR_TYPE.EXTERNAL, "External Error")} + {renderErrorTypeListItem(ERROR_TYPE.INSUFFICIENT_RESOURCES, "Resources Error")} + {renderErrorTypeListItem(ERROR_TYPE.USER_ERROR, "User Error")} +
    + +
    +   +
    + +
      + {renderSortListItem(SORT_TYPE.CREATED, "Creation Time")} + {renderSortListItem(SORT_TYPE.ELAPSED, "Elapsed Time")} + {renderSortListItem(SORT_TYPE.CPU, "CPU Time")} + {renderSortListItem(SORT_TYPE.EXECUTION, "Execution Time")} + {renderSortListItem(SORT_TYPE.CURRENT_MEMORY, "Current Memory")} + {renderSortListItem(SORT_TYPE.CUMULATIVE_MEMORY, "Cumulative User Memory")} +
    +
    +   +
    + +
      + {renderReorderListItem(1000, "1s")} + {renderReorderListItem(5000, "5s")} + {renderReorderListItem(10000, "10s")} + {renderReorderListItem(30000, "30s")} +
      + {renderReorderListItem(0, "Off")} +
    +
    +   +
    + +
      + {renderMaxQueriesListItem(20, "20 queries")} + {renderMaxQueriesListItem(50, "50 queries")} + {renderMaxQueriesListItem(100, "100 queries")} +
      + {renderMaxQueriesListItem(0, "All queries")} +
    - - {queryList} -
    - ); - } -} +
    + + {queryList} +
    + ); +}; From 7a5285dc2d1a9821d94d96c2bd05df8eabb894d6 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Fri, 1 Aug 2025 23:46:05 -0500 Subject: [PATCH 04/16] Fix setState calls; add deps array to update sparkline with data --- presto-ui/src/router/ClusterHUD.jsx | 85 ++++++++++++++++------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/presto-ui/src/router/ClusterHUD.jsx b/presto-ui/src/router/ClusterHUD.jsx index db5fae5fb3a4c..f5a4954e43742 100755 --- a/presto-ui/src/router/ClusterHUD.jsx +++ b/presto-ui/src/router/ClusterHUD.jsx @@ -59,55 +59,53 @@ export const ClusterHUD = () => { const resetTimer = () => { clearTimeout(timeoutId.current); - // stop refreshing when query finishes or fails - if (state.query === null || !state.ended) { - timeoutId.current = setTimeout(refreshLoop, 1000); - } + timeoutId.current = setTimeout(refreshLoop, 1000); }; const refreshLoop = () => { clearTimeout(timeoutId.current); // to stop multiple series of refreshLoop from going on simultaneously $.get('/v1/cluster', function (clusterState) { + setState(prevState => { + let newRowInputRate = []; + let newByteInputRate = []; + let newPerWorkerCpuTimeRate = []; + if (prevState.lastRefresh !== null) { + const rowsInputSinceRefresh = clusterState.totalInputRows - prevState.lastInputRows; + const bytesInputSinceRefresh = clusterState.totalInputBytes - prevState.lastInputBytes; + const cpuTimeSinceRefresh = clusterState.totalCpuTimeSecs - prevState.lastCpuTime; + const secsSinceRefresh = (Date.now() - prevState.lastRefresh) / 1000.0; - let newRowInputRate = []; - let newByteInputRate = []; - let newPerWorkerCpuTimeRate = []; - if (state.lastRefresh !== null) { - const rowsInputSinceRefresh = clusterState.totalInputRows - state.lastInputRows; - const bytesInputSinceRefresh = clusterState.totalInputBytes - state.lastInputBytes; - const cpuTimeSinceRefresh = clusterState.totalCpuTimeSecs - state.lastCpuTime; - const secsSinceRefresh = (Date.now() - state.lastRefresh) / 1000.0; - - newRowInputRate = addExponentiallyWeightedToHistory(rowsInputSinceRefresh / secsSinceRefresh, state.rowInputRate); - newByteInputRate = addExponentiallyWeightedToHistory(bytesInputSinceRefresh / secsSinceRefresh, state.byteInputRate); - newPerWorkerCpuTimeRate = addExponentiallyWeightedToHistory((cpuTimeSinceRefresh / clusterState.activeWorkers) / secsSinceRefresh, state.perWorkerCpuTimeRate); - } + newRowInputRate = addExponentiallyWeightedToHistory(rowsInputSinceRefresh / secsSinceRefresh, prevState.rowInputRate); + newByteInputRate = addExponentiallyWeightedToHistory(bytesInputSinceRefresh / secsSinceRefresh, prevState.byteInputRate); + newPerWorkerCpuTimeRate = addExponentiallyWeightedToHistory((cpuTimeSinceRefresh / clusterState.activeWorkers) / secsSinceRefresh, prevState.perWorkerCpuTimeRate); + } - setState({ - ...state, - // instantaneous stats - runningQueries: addToHistory(clusterState.runningQueries, state.runningQueries), - queuedQueries: addToHistory(clusterState.queuedQueries, state.queuedQueries), - blockedQueries: addToHistory(clusterState.blockedQueries, state.blockedQueries), - activeWorkers: addToHistory(clusterState.activeWorkers, state.activeWorkers), - clusterCount: addToHistory(clusterState.clusterCount, state.clusterCount), + return { + ...prevState, + // instantaneous stats + runningQueries: addToHistory(clusterState.runningQueries, prevState.runningQueries), + queuedQueries: addToHistory(clusterState.queuedQueries, prevState.queuedQueries), + blockedQueries: addToHistory(clusterState.blockedQueries, prevState.blockedQueries), + activeWorkers: addToHistory(clusterState.activeWorkers, prevState.activeWorkers), + clusterCount: addToHistory(clusterState.clusterCount, prevState.clusterCount), - // moving averages - runningDrivers: addExponentiallyWeightedToHistory(clusterState.runningDrivers, state.runningDrivers), - reservedMemory: addExponentiallyWeightedToHistory(clusterState.reservedMemory, state.reservedMemory), + // moving averages + runningDrivers: addExponentiallyWeightedToHistory(clusterState.runningDrivers, prevState.runningDrivers), + reservedMemory: addExponentiallyWeightedToHistory(clusterState.reservedMemory, prevState.reservedMemory), - // moving averages for diffs - rowInputRate: newRowInputRate, - byteInputRate: newByteInputRate, - perWorkerCpuTimeRate: newPerWorkerCpuTimeRate, + // moving averages for diffs + rowInputRate: newRowInputRate, + byteInputRate: newByteInputRate, + perWorkerCpuTimeRate: newPerWorkerCpuTimeRate, - lastInputRows: clusterState.totalInputRows, - lastInputBytes: clusterState.totalInputBytes, - lastCpuTime: clusterState.totalCpuTimeSecs, + lastInputRows: clusterState.totalInputRows, + lastInputBytes: clusterState.totalInputBytes, + lastCpuTime: clusterState.totalCpuTimeSecs, - initialized: true, + initialized: true, - lastRefresh: Date.now() + lastRefresh: Date.now() + }; }); resetTimer(); }) @@ -149,7 +147,18 @@ export const ClusterHUD = () => { } $('[data-bs-toggle="tooltip"]').tooltip(); - }); + }, [ + state.runningQueries, + state.blockedQueries, + state.queuedQueries, + state.activeWorkers, + state.clusterCount, + state.runningDrivers, + state.reservedMemory, + state.rowInputRate, + state.byteInputRate, + state.perWorkerCpuTimeRate + ]); return (
    From 2cc3d028a006d3112bcfe6be1aa047559b106b83 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Fri, 1 Aug 2025 23:47:16 -0500 Subject: [PATCH 05/16] Fix setState calls; fix bug with filter state getting reset --- presto-ui/src/router/QueryList.jsx | 214 +++++++++++++++-------------- 1 file changed, 113 insertions(+), 101 deletions(-) diff --git a/presto-ui/src/router/QueryList.jsx b/presto-ui/src/router/QueryList.jsx index 96b1e7d6bb39a..183ad92bbd8bc 100755 --- a/presto-ui/src/router/QueryList.jsx +++ b/presto-ui/src/router/QueryList.jsx @@ -299,10 +299,7 @@ export const QueryList = (props) => { const resetTimer = () => { clearTimeout(timeoutId.current); - // stop refreshing when query finishes or fails - if (state.query === null || !state.ended) { - timeoutId.current = setTimeout(refreshLoop, 1000); - } + timeoutId.current = setTimeout(refreshLoop, 1000); }; const refreshLoop = () => { @@ -310,52 +307,54 @@ export const QueryList = (props) => { clearTimeout(searchTimeoutId.current); $.get('/v1/query', function (queryList) { - const queryMap = queryList.reduce(function (map, query) { - map[query.queryId] = query; - return map; - }, {}); - - let updatedQueries = []; - state.displayedQueries.forEach(function (oldQuery) { - if (oldQuery.queryId in queryMap) { - updatedQueries.push(queryMap[oldQuery.queryId]); - queryMap[oldQuery.queryId] = false; - } - }); - - let newQueries = []; - for (const queryId in queryMap) { - if (queryMap[queryId]) { - newQueries.push(queryMap[queryId]); + setState(prevState => { + const queryMap = queryList.reduce(function (map, query) { + map[query.queryId] = query; + return map; + }, {}); + + let updatedQueries = []; + prevState.displayedQueries.forEach(function (oldQuery) { + if (oldQuery.queryId in queryMap) { + updatedQueries.push(queryMap[oldQuery.queryId]); + queryMap[oldQuery.queryId] = false; + } + }); + + let newQueries = []; + for (const queryId in queryMap) { + if (queryMap[queryId]) { + newQueries.push(queryMap[queryId]); + } } - } - newQueries = filterQueries(newQueries, state.stateFilters, state.errorTypeFilters, state.searchString); + newQueries = filterQueries(newQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); - const lastRefresh = Date.now(); - let lastReorder = state.lastReorder; + const lastRefresh = Date.now(); + let lastReorder = prevState.lastReorder; - if (state.reorderInterval !== 0 && ((lastRefresh - lastReorder) >= state.reorderInterval)) { - updatedQueries = filterQueries(updatedQueries, state.stateFilters, state.errorTypeFilters, state.searchString); - updatedQueries = updatedQueries.concat(newQueries); - sortAndLimitQueries(updatedQueries, state.currentSortType, state.currentSortOrder, 0); - lastReorder = Date.now(); - } - else { - sortAndLimitQueries(newQueries, state.currentSortType, state.currentSortOrder, 0); - updatedQueries = updatedQueries.concat(newQueries); - } + if (prevState.reorderInterval !== 0 && ((lastRefresh - lastReorder) >= prevState.reorderInterval)) { + updatedQueries = filterQueries(updatedQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); + updatedQueries = updatedQueries.concat(newQueries); + sortAndLimitQueries(updatedQueries, prevState.currentSortType, prevState.currentSortOrder, 0); + lastReorder = Date.now(); + } + else { + sortAndLimitQueries(newQueries, prevState.currentSortType, prevState.currentSortOrder, 0); + updatedQueries = updatedQueries.concat(newQueries); + } - if (state.maxQueries !== 0 && (updatedQueries.length > state.maxQueries)) { - updatedQueries.splice(state.maxQueries, (updatedQueries.length - state.maxQueries)); - } + if (prevState.maxQueries !== 0 && (updatedQueries.length > prevState.maxQueries)) { + updatedQueries.splice(prevState.maxQueries, (updatedQueries.length - prevState.maxQueries)); + } - setState({ - ...state, - allQueries: queryList, - displayedQueries: updatedQueries, - lastRefresh: lastRefresh, - lastReorder: lastReorder, - initialized: true + return { + ...prevState, + allQueries: queryList, + displayedQueries: updatedQueries, + lastRefresh: lastRefresh, + lastReorder: lastReorder, + initialized: true + }; }); resetTimer(); }) @@ -392,12 +391,14 @@ export const QueryList = (props) => { const executeSearch = () => { clearTimeout(searchTimeoutId.current); - const newDisplayedQueries = filterQueries(state.allQueries, state.stateFilters, state.errorTypeFilters, state.searchString); - sortAndLimitQueries(newDisplayedQueries, state.currentSortType, state.currentSortOrder, state.maxQueries); + setState(prevState => { + const newDisplayedQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); + sortAndLimitQueries(newDisplayedQueries, prevState.currentSortType, prevState.currentSortOrder, prevState.maxQueries); - setState({ - ...state, - displayedQueries: newDisplayedQueries + return { + ...prevState, + displayedQueries: newDisplayedQueries + }; }); }; @@ -409,13 +410,15 @@ export const QueryList = (props) => { }; const handleMaxQueriesClick = (newMaxQueries) => { - const filteredQueries = filterQueries(state.allQueries, state.stateFilters, state.errorTypeFilters, state.searchString); - sortAndLimitQueries(filteredQueries, state.currentSortType, state.currentSortOrder, newMaxQueries); - - setState({ - ...state, - maxQueries: newMaxQueries, - displayedQueries: filteredQueries + setState(prevState => { + const filteredQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); + sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder, newMaxQueries); + + return { + ...prevState, + maxQueries: newMaxQueries, + displayedQueries: filteredQueries + }; }); }; @@ -426,12 +429,15 @@ export const QueryList = (props) => { }; const handleReorderClick = (interval) => { - if (state.reorderInterval !== interval) { - setState({ - ...state, - reorderInterval: interval, - }); - } + setState(prevState => { + if (prevState.reorderInterval !== interval) { + return { + ...prevState, + reorderInterval: interval, + }; + } + return prevState; + }); }; const renderSortListItem = (sortType, sortText) => { @@ -456,21 +462,23 @@ export const QueryList = (props) => { }; const handleSortClick = (sortType) => { - const newSortType = sortType; - let newSortOrder = SORT_ORDER.DESCENDING; + setState(prevState => { + const newSortType = sortType; + let newSortOrder = SORT_ORDER.DESCENDING; - if (state.currentSortType === sortType && state.currentSortOrder === SORT_ORDER.DESCENDING) { - newSortOrder = SORT_ORDER.ASCENDING; - } + if (prevState.currentSortType === sortType && prevState.currentSortOrder === SORT_ORDER.DESCENDING) { + newSortOrder = SORT_ORDER.ASCENDING; + } - const newDisplayedQueries = filterQueries(state.allQueries, state.stateFilters, state.errorTypeFilters, state.searchString); - sortAndLimitQueries(newDisplayedQueries, newSortType, newSortOrder, state.maxQueries); + const newDisplayedQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); + sortAndLimitQueries(newDisplayedQueries, newSortType, newSortOrder, prevState.maxQueries); - setState({ - ...state, - displayedQueries: newDisplayedQueries, - currentSortType: newSortType, - currentSortOrder: newSortOrder + return { + ...prevState, + displayedQueries: newDisplayedQueries, + currentSortType: newSortType, + currentSortOrder: newSortOrder + }; }); }; @@ -490,21 +498,23 @@ export const QueryList = (props) => { }; const handleStateFilterClick = (filter) => { - const newFilters = state.stateFilters.slice(); - if (state.stateFilters.indexOf(filter) > -1) { - newFilters.splice(newFilters.indexOf(filter), 1); - } - else { - newFilters.push(filter); - } + setState(prevState => { + const newFilters = prevState.stateFilters.slice(); + if (prevState.stateFilters.indexOf(filter) > -1) { + newFilters.splice(newFilters.indexOf(filter), 1); + } + else { + newFilters.push(filter); + } - const filteredQueries = filterQueries(state.allQueries, newFilters, state.errorTypeFilters, state.searchString); - sortAndLimitQueries(filteredQueries, state.currentSortType, state.currentSortOrder); + const filteredQueries = filterQueries(prevState.allQueries, newFilters, prevState.errorTypeFilters, prevState.searchString); + sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder); - setState({ - ...state, - stateFilters: newFilters, - displayedQueries: filteredQueries + return { + ...prevState, + stateFilters: newFilters, + displayedQueries: filteredQueries + }; }); }; @@ -523,21 +533,23 @@ export const QueryList = (props) => { }; const handleErrorTypeFilterClick = (errorType) => { - const newFilters = state.errorTypeFilters.slice(); - if (state.errorTypeFilters.indexOf(errorType) > -1) { - newFilters.splice(newFilters.indexOf(errorType), 1); - } - else { - newFilters.push(errorType); - } + setState(prevState => { + const newFilters = prevState.errorTypeFilters.slice(); + if (prevState.errorTypeFilters.indexOf(errorType) > -1) { + newFilters.splice(newFilters.indexOf(errorType), 1); + } + else { + newFilters.push(errorType); + } - const filteredQueries = filterQueries(state.allQueries, state.stateFilters, newFilters, state.searchString); - sortAndLimitQueries(filteredQueries, state.currentSortType, state.currentSortOrder); + const filteredQueries = filterQueries(prevState.allQueries, prevState.stateFilters, newFilters, prevState.searchString); + sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder); - setState({ - ...state, - errorTypeFilters: newFilters, - displayedQueries: filteredQueries + return { + ...prevState, + errorTypeFilters: newFilters, + displayedQueries: filteredQueries + }; }); }; From 29396bc757035ee70e9553d8a5d29c699f915041 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Fri, 1 Aug 2025 23:47:55 -0500 Subject: [PATCH 06/16] Fix setState call --- presto-ui/src/router/PageTitle.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/presto-ui/src/router/PageTitle.jsx b/presto-ui/src/router/PageTitle.jsx index b45fc59139419..e148acc23d1f8 100755 --- a/presto-ui/src/router/PageTitle.jsx +++ b/presto-ui/src/router/PageTitle.jsx @@ -31,13 +31,13 @@ export const PageTitle = (props) => { fetch("/v1/info") .then(response => response.json()) .then(info => { - setState({ - ...state, + setState(prevState => ({ + ...prevState, info: info, noConnection: false, lastSuccess: Date.now(), modalShown: false, - }); + })); //$FlowFixMe$ Bootstrap 3 plugin $('#no-connection-modal').hide(); resetTimer(); From 610df35ed48f4e6f31fc66120a2516c2215bb4f6 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Mon, 4 Aug 2025 10:43:39 -0500 Subject: [PATCH 07/16] Add nullish coalescing operator check --- presto-ui/src/router/ClusterHUD.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presto-ui/src/router/ClusterHUD.jsx b/presto-ui/src/router/ClusterHUD.jsx index f5a4954e43742..002b3ec0888ac 100755 --- a/presto-ui/src/router/ClusterHUD.jsx +++ b/presto-ui/src/router/ClusterHUD.jsx @@ -146,7 +146,7 @@ export const ClusterHUD = () => { })); } - $('[data-bs-toggle="tooltip"]').tooltip(); + $('[data-bs-toggle="tooltip"]')?.tooltip?.(); }, [ state.runningQueries, state.blockedQueries, From 294f6e4b5c44bd87893cb9f88d3a37e148cae06d Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Mon, 4 Aug 2025 11:51:58 -0500 Subject: [PATCH 08/16] Refactor func, destructure props refs, remove unused arg --- presto-ui/src/router/QueryList.jsx | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/presto-ui/src/router/QueryList.jsx b/presto-ui/src/router/QueryList.jsx index 183ad92bbd8bc..513044d13e4e7 100755 --- a/presto-ui/src/router/QueryList.jsx +++ b/presto-ui/src/router/QueryList.jsx @@ -64,8 +64,7 @@ const stripQueryTextWhitespace = (queryText) => { return truncateString(formattedQueryText, 300); } -export const QueryListItem = (props) => { - const query = props.query; +export const QueryListItem = ({ query }) => { const progressBarStyle = {width: getProgressBarPercentage(query) + "%", backgroundColor: getQueryStateColor(query)}; const splitDetails = ( @@ -139,7 +138,7 @@ export const QueryListItem = (props) => {
       - {truncateString(user, 35)} + {truncateString(user, 35)}
    @@ -183,18 +182,13 @@ export const QueryListItem = (props) => { ); }; -const DisplayedQueriesList = (props) => { - const queryNodes = props.queries.map(function (query) { - return ( - - ); - }); - return ( -
    - {queryNodes} -
    - ); -}; +const DisplayedQueriesList = ({ queries }) => ( + <> + {queries.map((query) => ( + + ))} + +); const FILTER_TYPE = { RUNNING: function (query) { @@ -225,7 +219,7 @@ const SORT_ORDER = { DESCENDING: function (value) {return -value} }; -export const QueryList = (props) => { +export const QueryList = () => { const [state, setState] = useState({ allQueries: [], displayedQueries: [], From 39947aeb8fb19f67eab7adbbc5988ff577685abd Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Mon, 4 Aug 2025 14:05:52 -0500 Subject: [PATCH 09/16] Fix flow errors - remove unused prop, allow numeric timeoutid --- presto-ui/src/router/PageTitle.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/presto-ui/src/router/PageTitle.jsx b/presto-ui/src/router/PageTitle.jsx index e148acc23d1f8..b5ccdb2fd1666 100755 --- a/presto-ui/src/router/PageTitle.jsx +++ b/presto-ui/src/router/PageTitle.jsx @@ -14,7 +14,7 @@ //@flow import React, { useState, useEffect, useRef } from "react"; -export const PageTitle = (props) => { +export const PageTitle = () => { const [state, setState] = useState({ noConnection: false, lightShown: false, @@ -24,7 +24,7 @@ export const PageTitle = (props) => { errorText: null, }); - const timeoutId = useRef(null); + const timeoutId = useRef(null); const refreshLoop = () => { clearTimeout(timeoutId.current); From 8b1e53f0c8579b731b3347bc25eedf5706399279 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Tue, 2 Sep 2025 17:12:47 -0500 Subject: [PATCH 10/16] Fix flow errors --- presto-ui/src/router/PageTitle.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/presto-ui/src/router/PageTitle.jsx b/presto-ui/src/router/PageTitle.jsx index b5ccdb2fd1666..6eb1cf4e24a40 100755 --- a/presto-ui/src/router/PageTitle.jsx +++ b/presto-ui/src/router/PageTitle.jsx @@ -14,7 +14,7 @@ //@flow import React, { useState, useEffect, useRef } from "react"; -export const PageTitle = () => { +export const PageTitle = (): React.Node => { const [state, setState] = useState({ noConnection: false, lightShown: false, @@ -24,7 +24,7 @@ export const PageTitle = () => { errorText: null, }); - const timeoutId = useRef(null); + const timeoutId = useRef(null); const refreshLoop = () => { clearTimeout(timeoutId.current); From af25cc6fd728e766bb528ec2dd10c3aa7b54cab3 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Wed, 3 Sep 2025 11:44:27 -0500 Subject: [PATCH 11/16] Add back in check, needed for running queries --- presto-ui/src/router/ClusterHUD.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/presto-ui/src/router/ClusterHUD.jsx b/presto-ui/src/router/ClusterHUD.jsx index 002b3ec0888ac..8899c7944912d 100755 --- a/presto-ui/src/router/ClusterHUD.jsx +++ b/presto-ui/src/router/ClusterHUD.jsx @@ -58,8 +58,11 @@ export const ClusterHUD = () => { const timeoutId = useRef(null); const resetTimer = () => { - clearTimeout(timeoutId.current); + clearTimeout(timeoutId.current); + // stop refreshing when query finishes or fails + if (state.query === null || !this.state.ended) { timeoutId.current = setTimeout(refreshLoop, 1000); + } }; const refreshLoop = () => { From 40bc0fc2df3a31396143c59ad281d75304a8bfd3 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Fri, 24 Oct 2025 14:08:16 -0500 Subject: [PATCH 12/16] Fix state reference --- presto-ui/src/router/ClusterHUD.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presto-ui/src/router/ClusterHUD.jsx b/presto-ui/src/router/ClusterHUD.jsx index 8899c7944912d..b6649f3a800e8 100755 --- a/presto-ui/src/router/ClusterHUD.jsx +++ b/presto-ui/src/router/ClusterHUD.jsx @@ -60,7 +60,7 @@ export const ClusterHUD = () => { const resetTimer = () => { clearTimeout(timeoutId.current); // stop refreshing when query finishes or fails - if (state.query === null || !this.state.ended) { + if (state.query === null || !state.ended) { timeoutId.current = setTimeout(refreshLoop, 1000); } }; From e6f31648c25d810dc6d08ede9b0da1cedc9cd618 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Fri, 24 Oct 2025 14:25:43 -0500 Subject: [PATCH 13/16] Remove unnecessary logic --- presto-ui/src/router/QueryList.jsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/presto-ui/src/router/QueryList.jsx b/presto-ui/src/router/QueryList.jsx index 513044d13e4e7..be091859c162d 100755 --- a/presto-ui/src/router/QueryList.jsx +++ b/presto-ui/src/router/QueryList.jsx @@ -116,11 +116,6 @@ export const QueryListItem = ({ query }) => {
    ); let user = ({query.session.user}); - if (query.session.principal) { - user = ( - {query.session.user} - ); - } return (
    From 13c87643ad007e00b5bed5c3001ee8a246441ab2 Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Fri, 24 Oct 2025 15:52:25 -0500 Subject: [PATCH 14/16] Prefer destructuring --- presto-ui/src/router/PageTitle.jsx | 2 +- presto-ui/src/router/QueryList.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/presto-ui/src/router/PageTitle.jsx b/presto-ui/src/router/PageTitle.jsx index 6eb1cf4e24a40..c32caf237cad4 100755 --- a/presto-ui/src/router/PageTitle.jsx +++ b/presto-ui/src/router/PageTitle.jsx @@ -84,7 +84,7 @@ export const PageTitle = (): React.Node => { return ; }; - const info = state.info; + const { info } = state; if (!info) { return null; } diff --git a/presto-ui/src/router/QueryList.jsx b/presto-ui/src/router/QueryList.jsx index be091859c162d..55f7abfd6a883 100755 --- a/presto-ui/src/router/QueryList.jsx +++ b/presto-ui/src/router/QueryList.jsx @@ -319,7 +319,7 @@ export const QueryList = () => { newQueries = filterQueries(newQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); const lastRefresh = Date.now(); - let lastReorder = prevState.lastReorder; + let { lastReorder } = prevState; if (prevState.reorderInterval !== 0 && ((lastRefresh - lastReorder) >= prevState.reorderInterval)) { updatedQueries = filterQueries(updatedQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); From e0cfe1e95b846fb131df8c3ae244a984ff8f088d Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Fri, 24 Oct 2025 16:00:33 -0500 Subject: [PATCH 15/16] Remove unnecessary logic controlling polling cycle --- presto-ui/src/router/ClusterHUD.jsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/presto-ui/src/router/ClusterHUD.jsx b/presto-ui/src/router/ClusterHUD.jsx index b6649f3a800e8..002b3ec0888ac 100755 --- a/presto-ui/src/router/ClusterHUD.jsx +++ b/presto-ui/src/router/ClusterHUD.jsx @@ -58,11 +58,8 @@ export const ClusterHUD = () => { const timeoutId = useRef(null); const resetTimer = () => { - clearTimeout(timeoutId.current); - // stop refreshing when query finishes or fails - if (state.query === null || !state.ended) { + clearTimeout(timeoutId.current); timeoutId.current = setTimeout(refreshLoop, 1000); - } }; const refreshLoop = () => { From 3d59ec9d5cd88aa01c0bc30be0c1aa99f88a731c Mon Sep 17 00:00:00 2001 From: Chris Matzenbach Date: Fri, 24 Oct 2025 16:25:56 -0500 Subject: [PATCH 16/16] Refactor sortAndLimitQueries to avoid argument mutation --- presto-ui/src/router/QueryList.jsx | 33 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/presto-ui/src/router/QueryList.jsx b/presto-ui/src/router/QueryList.jsx index 55f7abfd6a883..ee6f141e94a22 100755 --- a/presto-ui/src/router/QueryList.jsx +++ b/presto-ui/src/router/QueryList.jsx @@ -234,13 +234,14 @@ export const QueryList = () => { const searchTimeoutId = useRef(null); const sortAndLimitQueries = (queries, sortType, sortOrder, maxQueries) => { - queries.sort(function (queryA, queryB) { + const sorted = [...queries].sort(function (queryA, queryB) { return sortOrder(sortType(queryA) - sortType(queryB)); }); - if (maxQueries !== 0 && queries.length > maxQueries) { - queries.splice(maxQueries, (queries.length - maxQueries)); + if (maxQueries !== 0 && sorted.length > maxQueries) { + return sorted.slice(0, maxQueries); } + return sorted; }; const filterQueries = (queries, stateFilters, errorTypeFilters, searchString) => { @@ -324,16 +325,16 @@ export const QueryList = () => { if (prevState.reorderInterval !== 0 && ((lastRefresh - lastReorder) >= prevState.reorderInterval)) { updatedQueries = filterQueries(updatedQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); updatedQueries = updatedQueries.concat(newQueries); - sortAndLimitQueries(updatedQueries, prevState.currentSortType, prevState.currentSortOrder, 0); + updatedQueries = sortAndLimitQueries(updatedQueries, prevState.currentSortType, prevState.currentSortOrder, 0); lastReorder = Date.now(); } else { - sortAndLimitQueries(newQueries, prevState.currentSortType, prevState.currentSortOrder, 0); + newQueries = sortAndLimitQueries(newQueries, prevState.currentSortType, prevState.currentSortOrder, 0); updatedQueries = updatedQueries.concat(newQueries); } if (prevState.maxQueries !== 0 && (updatedQueries.length > prevState.maxQueries)) { - updatedQueries.splice(prevState.maxQueries, (updatedQueries.length - prevState.maxQueries)); + updatedQueries = updatedQueries.slice(0, prevState.maxQueries); } return { @@ -381,8 +382,8 @@ export const QueryList = () => { clearTimeout(searchTimeoutId.current); setState(prevState => { - const newDisplayedQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); - sortAndLimitQueries(newDisplayedQueries, prevState.currentSortType, prevState.currentSortOrder, prevState.maxQueries); + let newDisplayedQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); + newDisplayedQueries = sortAndLimitQueries(newDisplayedQueries, prevState.currentSortType, prevState.currentSortOrder, prevState.maxQueries); return { ...prevState, @@ -400,8 +401,8 @@ export const QueryList = () => { const handleMaxQueriesClick = (newMaxQueries) => { setState(prevState => { - const filteredQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); - sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder, newMaxQueries); + let filteredQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); + filteredQueries = sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder, newMaxQueries); return { ...prevState, @@ -459,8 +460,8 @@ export const QueryList = () => { newSortOrder = SORT_ORDER.ASCENDING; } - const newDisplayedQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); - sortAndLimitQueries(newDisplayedQueries, newSortType, newSortOrder, prevState.maxQueries); + let newDisplayedQueries = filterQueries(prevState.allQueries, prevState.stateFilters, prevState.errorTypeFilters, prevState.searchString); + newDisplayedQueries = sortAndLimitQueries(newDisplayedQueries, newSortType, newSortOrder, prevState.maxQueries); return { ...prevState, @@ -496,8 +497,8 @@ export const QueryList = () => { newFilters.push(filter); } - const filteredQueries = filterQueries(prevState.allQueries, newFilters, prevState.errorTypeFilters, prevState.searchString); - sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder); + let filteredQueries = filterQueries(prevState.allQueries, newFilters, prevState.errorTypeFilters, prevState.searchString); + filteredQueries = sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder, prevState.maxQueries); return { ...prevState, @@ -531,8 +532,8 @@ export const QueryList = () => { newFilters.push(errorType); } - const filteredQueries = filterQueries(prevState.allQueries, prevState.stateFilters, newFilters, prevState.searchString); - sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder); + let filteredQueries = filterQueries(prevState.allQueries, prevState.stateFilters, newFilters, prevState.searchString); + filteredQueries = sortAndLimitQueries(filteredQueries, prevState.currentSortType, prevState.currentSortOrder, prevState.maxQueries); return { ...prevState,