From 73a328f37b2749ceee4dc9f3a3370b8522a24f4d Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Wed, 28 Aug 2024 14:54:56 +0200 Subject: [PATCH] Memoize and improve targets page filtering Signed-off-by: Julius Volz --- .../src/pages/targets/ScrapePoolsList.tsx | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/web/ui/mantine-ui/src/pages/targets/ScrapePoolsList.tsx b/web/ui/mantine-ui/src/pages/targets/ScrapePoolsList.tsx index 05521a596..5f7e5fea2 100644 --- a/web/ui/mantine-ui/src/pages/targets/ScrapePoolsList.tsx +++ b/web/ui/mantine-ui/src/pages/targets/ScrapePoolsList.tsx @@ -19,7 +19,7 @@ import { } from "@tabler/icons-react"; import { useSuspenseAPIQuery } from "../../api/api"; import { Target, TargetsResult } from "../../api/responseTypes/targets"; -import React, { FC } from "react"; +import React, { FC, useMemo } from "react"; import { humanizeDurationRelative, humanizeDuration, @@ -80,10 +80,11 @@ const kvSearch = new KVSearch({ indexedKeys: ["labels", "scrapePool", ["labels", /.*/]], }); -const groupTargets = ( +const buildPoolsData = ( poolNames: string[], - allTargets: Target[], - shownTargets: Target[] + targets: Target[], + search: string, + healthFilter: (string | null)[] ): ScrapePools => { const pools: ScrapePools = {}; @@ -97,7 +98,7 @@ const groupTargets = ( }; } - for (const target of allTargets) { + for (const target of targets) { if (!pools[target.scrapePool]) { // TODO: Should we do better here? throw new Error( @@ -120,7 +121,16 @@ const groupTargets = ( } } - for (const target of shownTargets) { + const filteredTargets: Target[] = ( + search === "" + ? targets + : kvSearch.filter(search, targets).map((value) => value.original) + ).filter( + (target) => + healthFilter.length === 0 || healthFilter.includes(target.health) + ); + + for (const target of filteredTargets) { pools[target.scrapePool].targets.push(target); } @@ -140,12 +150,6 @@ const ScrapePoolList: FC = ({ healthFilter, searchFilter, }) => { - const dispatch = useAppDispatch(); - const [showEmptyPools, setShowEmptyPools] = useQueryParam( - "showEmptyPools", - withDefault(BooleanParam, true) - ); - // Based on the selected pool (if any), load the list of targets. const { data: { @@ -159,31 +163,29 @@ const ScrapePoolList: FC = ({ }, }); + const dispatch = useAppDispatch(); + const [showEmptyPools, setShowEmptyPools] = useQueryParam( + "showEmptyPools", + withDefault(BooleanParam, true) + ); + const { collapsedPools, showLimitAlert } = useAppSelector( (state) => state.targetsPage ); - const [debouncedSearch] = useDebouncedValue(searchFilter, 250); + const [debouncedSearch] = useDebouncedValue(searchFilter.trim(), 250); - // TODO: Memoize all this computation, especially groupTargets(). - const search = debouncedSearch.trim(); - const healthFilteredTargets = activeTargets.filter( - (target) => - healthFilter.length === 0 || - healthFilter.includes(target.health.toLowerCase()) + const allPools = useMemo( + () => + buildPoolsData( + selectedPool ? [selectedPool] : poolNames, + activeTargets, + debouncedSearch, + healthFilter + ), + [selectedPool, poolNames, activeTargets, debouncedSearch, healthFilter] ); - const filteredTargets = - search === "" - ? healthFilteredTargets - : kvSearch - .filter(search, healthFilteredTargets) - .map((value) => value.original); - const allPools = groupTargets( - selectedPool ? [selectedPool] : poolNames, - activeTargets, - filteredTargets - ); const allPoolNames = Object.keys(allPools); const shownPoolNames = showEmptyPools ? allPoolNames