From 5d4d8de2354a2003c66f3734400c98e3df09f003 Mon Sep 17 00:00:00 2001 From: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> Date: Sat, 17 Oct 2026 19:16:08 +0530 Subject: [PATCH 1/3] Keep a typed alert argument search when the source search is rebuilt Adding a filter re-asks the server what the selection supports, which hands the argument autocomplete a new sourceSearch. debouncedSearch depended on it, so it was rebuilt and the cleanup cancelled the search the user was still typing: the text stayed in the input but no search request was ever sent. Read the search params through a ref so the debounced function is created once and only cancelled on unmount. This is the cause of the intermittent NotificationAlerts > Multiple Filters Alert timeouts in the merge queue. --- .../AlertAiFormFields.component.test.tsx | 59 ++++++++++++++++++- .../Alerts/AlertAiRuleSection.component.tsx | 25 ++++++-- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx index 94c836415c7e..aa83e4bbee7a 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx @@ -53,12 +53,15 @@ import { import { testAlertDestination } from '../../../rest/alertsAPI'; import { searchQuery } from '../../../rest/searchAPI'; import alertsClassBase from '../../../utils/AlertsClassBase'; +import { AlertSourceSearch } from '../../../utils/Alerts/AlertSourceSearch'; import AlertAiDestinationConfigFields from './AlertAiDestinationConfigFields.component'; import AlertAiDestinationItem from './AlertAiDestinationItem.component'; import AlertAiDestinationSection from './AlertAiDestinationSection.component'; import AlertAiForm from './AlertAiForm.component'; import AlertAiFormFields from './AlertAiFormFields.component'; -import AlertAiRuleSection from './AlertAiRuleSection.component'; +import AlertAiRuleSection, { + RuleArgumentField, +} from './AlertAiRuleSection.component'; import AlertAiSection from './AlertAiSection.component'; import AlertDescriptionCard from './AlertDescriptionCard.component'; @@ -859,6 +862,60 @@ describe('AlertAi form field components', () => { ); }); + it('keeps a typed search when the source search is rebuilt during the debounce', async () => { + jest.useFakeTimers(); + const getSourceSearch = () => + ({ + byId: jest.fn(), + byName: jest.fn(), + containerEntities: [], + indexes: [], + } as unknown as AlertSourceSearch); + const value = { + ...baseValue, + input: { + filters: [ + { + arguments: [{ input: [], name: 'domainList' }], + effect: Effect.Include, + name: 'matchAnyDomain', + }, + ], + }, + } as ModifiedCreateEventSubscription; + const renderField = (sourceSearch: AlertSourceSearch) => ( + + ); + + const { rerender } = render(renderField(getSourceSearch())); + await act(async () => { + jest.advanceTimersByTime(0); + }); + (searchQuery as jest.Mock).mockClear(); + + fireEvent.change(screen.getByTestId('domainList-autocomplete'), { + target: { value: 'dom' }, + }); + // Adding a filter re-asks the server what the selection supports, which hands the field + // a new source search while the typed text is still waiting on the debounce. + rerender(renderField(getSourceSearch())); + await act(async () => { + jest.advanceTimersByTime(500); + }); + + expect(searchQuery).toHaveBeenCalledWith( + expect.objectContaining({ query: 'dom' }) + ); + }); + it('renders fixed runtime options with the fqn autocomplete contract', () => { const onChange = jest.fn(); const selectedRule: ArgumentsInput = { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiRuleSection.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiRuleSection.component.tsx index f63728690fe5..dbf7296213a3 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiRuleSection.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiRuleSection.component.tsx @@ -316,15 +316,30 @@ const AiArgumentAutocomplete = ({ [hasNoResults, items, t] ); + // Read through a ref so a new source search (the server re-answers capabilities whenever the + // filters change) does not recreate, and so cancel, a search the user is still typing. + const searchParamsRef = useRef({ + argument, + containerEntities: stableContainerEntities, + selectedSource, + sourceSearch, + }); + + useEffect(() => { + searchParamsRef.current = { + argument, + containerEntities: stableContainerEntities, + selectedSource, + sourceSearch, + }; + }, [argument, selectedSource, sourceSearch, stableContainerEntities]); + const debouncedSearch = useMemo( () => debounce(async (searchText: string) => { const nextItems = await searchAlertAiArgumentOptions({ - argument, - containerEntities: stableContainerEntities, + ...searchParamsRef.current, searchText, - selectedSource, - sourceSearch, }); setHasNoResults(searchText.trim() !== '' && nextItems.length === 0); @@ -336,7 +351,7 @@ const AiArgumentAutocomplete = ({ ) ); }, 500), - [argument, selectedSource, sourceSearch, stableContainerEntities] + [] ); useEffect( From 95f3e255819a0c9e4ec1d1c90ce4bc430cffabb0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 17 Oct 2026 13:47:10 +0000 Subject: [PATCH 2/3] chore(playwright): auto-refresh impact-map.generated.json --- .github/playwright/impact-map.generated.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/playwright/impact-map.generated.json b/.github/playwright/impact-map.generated.json index a5c2053bdd35..4748d14360fc 100644 --- a/.github/playwright/impact-map.generated.json +++ b/.github/playwright/impact-map.generated.json @@ -3328,6 +3328,7 @@ "playwright/e2e/Features/AdvancedSearch.spec.ts", "playwright/e2e/Features/ContextCenterDashboard.spec.ts", "playwright/e2e/Features/DataQuality/IncidentManagerSqlQuery.spec.ts", + "playwright/e2e/Features/DataQuality/ProfilerIngestionForm.spec.ts", "playwright/e2e/Features/DataQuality/TableTestCaseExportFilters.spec.ts", "playwright/e2e/Features/DomainFilterQueryFilter.spec.ts", "playwright/e2e/Features/LandingPageWidgets/LandingPageContextCenter.spec.ts", @@ -8668,6 +8669,7 @@ "openmetadata-ui/src/main/resources/ui/src/components/Settings/Services/AddIngestion/AddIngestion.component.tsx" ], "specs": [ + "playwright/e2e/Features/DataQuality/ProfilerIngestionForm.spec.ts", "playwright/e2e/Features/StorageMetadataAgentForm.spec.ts" ] }, From 2ff8254295be0423f1cfb1e69e943c307b926159 Mon Sep 17 00:00:00 2001 From: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com> Date: Sat, 17 Oct 2026 22:31:39 +0530 Subject: [PATCH 3/3] Fix UI checkstyle --- .../observability/Alerts/AlertAiFormFields.component.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx index aa83e4bbee7a..4f6dfb81172b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/observability/Alerts/AlertAiFormFields.component.test.tsx @@ -52,8 +52,8 @@ import { } from '../../../pages/AddObservabilityPage/AddObservabilityPage.interface'; import { testAlertDestination } from '../../../rest/alertsAPI'; import { searchQuery } from '../../../rest/searchAPI'; -import alertsClassBase from '../../../utils/AlertsClassBase'; import { AlertSourceSearch } from '../../../utils/Alerts/AlertSourceSearch'; +import alertsClassBase from '../../../utils/AlertsClassBase'; import AlertAiDestinationConfigFields from './AlertAiDestinationConfigFields.component'; import AlertAiDestinationItem from './AlertAiDestinationItem.component'; import AlertAiDestinationSection from './AlertAiDestinationSection.component';