Alerting: Fix no search results loop for new list UI (#101513)

This commit is contained in:
Gilles De Mey
2025-03-03 17:14:34 +02:00
committed by GitHub
parent 41ab914da2
commit 2430e21ffa
2 changed files with 17 additions and 6 deletions
@@ -1,4 +1,5 @@
import { take, tap, withAbort } from 'ix/asynciterable/operators';
import { empty } from 'ix/asynciterable';
import { catchError, take, tap, withAbort } from 'ix/asynciterable/operators';
import { useEffect, useRef, useState, useTransition } from 'react';
import { Card, EmptyState, Stack, Text } from '@grafana/ui';
@@ -75,7 +76,12 @@ function FilterViewResults({ filterState }: FilterViewProps) {
/* This function will fetch a page of results from the iterable */
const [{ execute: loadResultPage }, state] = useAsync(async () => {
for await (const rule of rulesIterator.current.pipe(take(FRONTENT_PAGE_SIZE))) {
for await (const rule of rulesIterator.current.pipe(
// grab <FRONTENT_PAGE_SIZE> from the rules iterable
take(FRONTENT_PAGE_SIZE),
// if an error occurs trying to fetch a page, return an empty iterable so the front-end isn't caught in an infinite loop
catchError(() => empty())
)) {
startTransition(() => {
// Rule key could be computed on the fly, but we do it here to avoid recalculating it with each render
// It's a not trivial computation because it involves hashing the rule
@@ -1,4 +1,4 @@
import { AsyncIterableX, from } from 'ix/asynciterable/index';
import { AsyncIterableX, empty, from } from 'ix/asynciterable';
import { merge } from 'ix/asynciterable/merge';
import { filter, flatMap, map } from 'ix/asynciterable/operators';
import { compact } from 'lodash';
@@ -68,11 +68,16 @@ export function useFilteredRulesIteratorProvider() {
map(([group, rule]) => mapGrafanaRuleToRuleWithOrigin(group, rule))
);
const [source, ...iterables] = ruleSourcesToFetchFrom.map((ds) => {
return from(prometheusGroupsGenerator(ds, groupLimit)).pipe(map((group) => [ds, group] as const));
const sourceIterables = ruleSourcesToFetchFrom.map((ds) => {
const generator = prometheusGroupsGenerator(ds, groupLimit);
return from(generator).pipe(map((group) => [ds, group] as const));
});
const dataSourcesIterator = merge(source, ...iterables).pipe(
// if we have no prometheus data sources, use an empty async iterable
const source = sourceIterables.at(0) ?? empty();
const otherIterables = sourceIterables.slice(1);
const dataSourcesIterator = merge(source, ...otherIterables).pipe(
filter(([_, group]) => groupFilter(group, normalizedFilterState)),
flatMap(([rulesSource, group]) => group.rules.map((rule) => [rulesSource, group, rule] as const)),
filter(([_, __, rule]) => ruleFilter(rule, filterState)),