From aa68f6045648b8a939158e05ca48f9e1f7177fa5 Mon Sep 17 00:00:00 2001 From: Evan Purkhiser Date: Wed, 19 Nov 2025 17:02:21 -0500 Subject: [PATCH] ref(crons): Invalidate monitor query after environment muting Part of [NEW-564: There needs to be some way to mute the entire cron detector](https://linear.app/getsentry/issue/NEW-564/there-needs-to-be-some-way-to-mute-the-entire-cron-detector) Changes the monitor update flow to invalidate the query cache instead of manually updating cached data when muting/unmuting monitor environments. This ensures the UI always reflects the latest environment data from the server, including mute status and other environment properties. - Simplified onUpdate to invalidate query instead of manually merging data - Removed manual cache updates in DetailsTimeline - Fixed mute action label to check actual environment mute status - Cleaned up unused import --- .../app/views/alerts/rules/crons/details.tsx | 23 +++++++------------ .../crons/components/detailsTimeline.tsx | 21 ++++------------- .../overviewTimeline/overviewRow.tsx | 5 +--- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/static/app/views/alerts/rules/crons/details.tsx b/static/app/views/alerts/rules/crons/details.tsx index ffe5e1e216d77d..2e7f5eb085e725 100644 --- a/static/app/views/alerts/rules/crons/details.tsx +++ b/static/app/views/alerts/rules/crons/details.tsx @@ -15,7 +15,7 @@ import {TimezoneProvider, useTimezone} from 'sentry/components/timezoneProvider' import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {RouteComponentProps} from 'sentry/types/legacyReactRouter'; -import {setApiQueryData, useApiQuery, useQueryClient} from 'sentry/utils/queryClient'; +import {useApiQuery, useQueryClient} from 'sentry/utils/queryClient'; import useApi from 'sentry/utils/useApi'; import useOrganization from 'sentry/utils/useOrganization'; import {DetailsSidebar} from 'sentry/views/insights/crons/components/detailsSidebar'; @@ -73,26 +73,19 @@ function MonitorDetails({params, location}: Props) { monitorSlug: params.monitorSlug, }); - function onUpdate(data: Monitor) { - const updatedMonitor = { - ...data, - // TODO(davidenwang): This is a bit of a hack, due to the PUT request - // which pauses/unpauses a monitor not returning monitor environments - // we should reuse the environments retrieved from the initial request - environments: monitor?.environments, - }; - setApiQueryData(queryClient, queryKey, updatedMonitor); + function onUpdate() { + // Invalidate the query to refetch the monitor with updated environment data. + // The PUT request doesn't return environments, so we need to refetch to get + // the latest environment muting status and other environment data. + queryClient.invalidateQueries({queryKey}); } const handleUpdate = async (data: Partial) => { if (monitor === undefined) { return; } - const resp = await updateMonitor(api, organization.slug, monitor, data); - - if (resp !== null) { - onUpdate(resp); - } + await updateMonitor(api, organization.slug, monitor, data); + onUpdate(); }; const userTimezone = useTimezone(); diff --git a/static/app/views/insights/crons/components/detailsTimeline.tsx b/static/app/views/insights/crons/components/detailsTimeline.tsx index fd47071a1983a1..cbeac0194909be 100644 --- a/static/app/views/insights/crons/components/detailsTimeline.tsx +++ b/static/app/views/insights/crons/components/detailsTimeline.tsx @@ -66,7 +66,9 @@ export function DetailsTimeline({monitor, onStatsLoaded, onEnvironmentUpdated}: organization, monitor.project.slug, monitor.slug, - {...location.query} + { + environment: location.query.environment, + } ); const {data: monitorStats} = useMonitorStats({ @@ -110,21 +112,8 @@ export function DetailsTimeline({monitor, onStatsLoaded, onEnvironmentUpdated}: return; } - setApiQueryData(queryClient, monitorDetailsQueryKey, oldMonitorDetails => { - return oldMonitorDetails - ? { - ...oldMonitorDetails, - environments: oldMonitorDetails.environments.map(monitorEnv => - monitorEnv.name === env - ? { - ...monitorEnv, - isMuted, - } - : monitorEnv - ), - } - : undefined; - }); + // Invalidate the query to refetch the monitor with updated environment data + queryClient.invalidateQueries({queryKey: monitorDetailsQueryKey}); onEnvironmentUpdated?.(); }; diff --git a/static/app/views/insights/crons/components/overviewTimeline/overviewRow.tsx b/static/app/views/insights/crons/components/overviewTimeline/overviewRow.tsx index 4da6aa8065227a..0ef465c2273930 100644 --- a/static/app/views/insights/crons/components/overviewTimeline/overviewRow.tsx +++ b/static/app/views/insights/crons/components/overviewTimeline/overviewRow.tsx @@ -147,10 +147,7 @@ export function OverviewRow({ ...(onToggleMuteEnvironment ? [ (env: string, isMuted: boolean) => ({ - label: - isMuted && !monitor.isMuted - ? t('Unmute Environment') - : t('Mute Environment'), + label: isMuted ? t('Unmute Environment') : t('Mute Environment'), key: 'mute', details: monitor.isMuted ? t('Monitor is muted') : undefined, disabled: monitor.isMuted,