From 47e999b4c65c6e8dd863784d0bdf24bcce662052 Mon Sep 17 00:00:00 2001 From: Feroze Mohideen Date: Wed, 4 Oct 2023 13:43:14 -0400 Subject: [PATCH] Refactor activity feed + filter non-zero exit code events (#3728) --- .../tabs/activity-feed/ActivityFeed.tsx | 116 ++++++++---------- 1 file changed, 51 insertions(+), 65 deletions(-) diff --git a/dashboard/src/main/home/app-dashboard/app-view/tabs/activity-feed/ActivityFeed.tsx b/dashboard/src/main/home/app-dashboard/app-view/tabs/activity-feed/ActivityFeed.tsx index 8a13e99317..7dbbd321ea 100644 --- a/dashboard/src/main/home/app-dashboard/app-view/tabs/activity-feed/ActivityFeed.tsx +++ b/dashboard/src/main/home/app-dashboard/app-view/tabs/activity-feed/ActivityFeed.tsx @@ -16,6 +16,8 @@ import _ from "lodash"; import Button from "components/porter/Button"; import { PorterAppEvent, porterAppEventValidator } from "./events/types"; import { z } from "zod"; +import { useQuery } from "@tanstack/react-query"; +import axios from "axios"; type Props = { appName: string; @@ -27,18 +29,22 @@ type Props = { const EVENTS_POLL_INTERVAL = 5000; // poll every 5 seconds const ActivityFeed: React.FC = ({ appName, deploymentTargetId, currentCluster, currentProject }) => { - const [events, setEvents] = useState([]); - const [loading, setLoading] = useState(true); + const [events, setEvents] = useState(undefined); const [hasError, setHasError] = useState(false); const [page, setPage] = useState(1); const [numPages, setNumPages] = useState(0); - const [hasPorterAgent, setHasPorterAgent] = useState(false); + const [hasPorterAgent, setHasPorterAgent] = useState(undefined); const [isPorterAgentInstalling, setIsPorterAgentInstalling] = useState(false); const [shouldAnimate, setShouldAnimate] = useState(true); - const getEvents = async () => { - setLoading(true) - try { + // remove this filter when https://linear.app/porter/issue/POR-1676/disable-porter-agent-code-for-cpu-alerts is resolved + const isNotFilteredAppEvent = (event: PorterAppEvent) => { + return !(event.type === "APP_EVENT" && event.metadata?.short_summary?.includes("non-zero exit code")); + } + + const { data: eventFetchData, isLoading: isEventFetchLoading, isRefetching } = useQuery( + ["appEvents", deploymentTargetId, page], + async () => { const res = await api.appEvents( "", { @@ -52,20 +58,25 @@ const ActivityFeed: React.FC = ({ appName, deploymentTargetId, currentClu } ); - setNumPages(res.data.num_pages); - const events = z.array(porterAppEventValidator).optional().default([]).parse(res.data.events); - setEvents(events); - setHasError(false) - } catch (err) { - setHasError(true); - console.log(err); - } finally { - setLoading(false); - setShouldAnimate(false); + const parsed = await z.object({ events: z.array(porterAppEventValidator).optional().default([]), num_pages: z.number() }).parseAsync(res.data); + return { events: parsed.events.filter(isNotFilteredAppEvent), pages: parsed.num_pages }; + }, + { + enabled: hasPorterAgent, + refetchInterval: EVENTS_POLL_INTERVAL, } - }; + ); + useEffect(() => { + if (eventFetchData && isRefetching) { + setEvents(eventFetchData.events); + setNumPages(eventFetchData.pages); + } + }, [eventFetchData, isRefetching]); const getLatestDeployEventIndex = () => { + if (events == null) { + return -1; + } const deployEvents = events.filter((event) => event.type === 'DEPLOY'); if (deployEvents.length === 0) { return -1; @@ -73,55 +84,30 @@ const ActivityFeed: React.FC = ({ appName, deploymentTargetId, currentClu return events.indexOf(deployEvents[0]); }; - const updateEvents = async () => { - try { - const res = await api.appEvents( - "", - { - deployment_target_id: deploymentTargetId, - page - }, - { - cluster_id: currentCluster, - project_id: currentProject, - porter_app_name: appName, + const { data: porterAgentCheck, isLoading: porterAgentCheckLoading } = useQuery( + ["detectPorterAgent", currentProject, currentCluster], + async () => { + const res = await api.detectPorterAgent("", {}, { project_id: currentProject, cluster_id: currentCluster }); + // response will either have version key if porter agent found, or error key if not + const parsed = await z.object({ version: z.string().optional() }).parseAsync(res.data); + return parsed.version === "v3"; + }, + { + enabled: !hasPorterAgent, + retry: (_, error) => { + if (axios.isAxiosError(error) && error.response?.status === 404) { + setHasPorterAgent(false); } - ); - setHasError(false) - setNumPages(res.data.num_pages); - const events = z.array(porterAppEventValidator).optional().default([]).parse(res.data.events); - setEvents(events); - } catch (err) { - setHasError(true); + return false; + }, + refetchOnWindowFocus: false, } - } - + ); useEffect(() => { - const checkForAgent = async () => { - try { - const project_id = currentProject; - const cluster_id = currentCluster; - const res = await api.detectPorterAgent("", {}, { project_id, cluster_id }); - const hasAgent = res.data?.version === "v3"; - setHasPorterAgent(hasAgent); - } catch (err) { - if (err.response?.status === 404) { - setHasPorterAgent(false); - } - } finally { - setLoading(false); - } - }; - - if (!hasPorterAgent) { - checkForAgent(); - } else { - const intervalId = setInterval(updateEvents, EVENTS_POLL_INTERVAL); - getEvents(); - return () => clearInterval(intervalId); + if (porterAgentCheck != null) { + setHasPorterAgent(porterAgentCheck); } - - }, [currentProject, currentCluster, hasPorterAgent, page]); + }, [porterAgentCheck]) const installAgent = async () => { const project_id = currentProject; @@ -157,7 +143,7 @@ const ActivityFeed: React.FC = ({ appName, deploymentTargetId, currentClu ); } - if (loading) { + if (isEventFetchLoading || porterAgentCheckLoading || events == null) { return (
@@ -166,7 +152,7 @@ const ActivityFeed: React.FC = ({ appName, deploymentTargetId, currentClu ); } - if (!loading && !hasPorterAgent) { + if (hasPorterAgent != null && !hasPorterAgent) { return (
@@ -184,7 +170,7 @@ const ActivityFeed: React.FC = ({ appName, deploymentTargetId, currentClu ); } - if (!loading && events?.length === 0) { + if (events != null && events.length === 0) { return (
No events found for "{appName}"