Bladeren bron

Implement websocket stream to get jobs instead of api endpoint

jnfrati 4 jaren geleden
bovenliggende
commit
e6abcc159e
1 gewijzigde bestanden met toevoegingen van 119 en 37 verwijderingen
  1. 119 37
      dashboard/src/main/home/cluster-dashboard/expanded-chart/jobs/useJobs.ts

+ 119 - 37
dashboard/src/main/home/cluster-dashboard/expanded-chart/jobs/useJobs.ts

@@ -21,6 +21,8 @@ export const useJobs = (chart: ChartType) => {
   );
   );
   const [jobs, setJobs] = useState([]);
   const [jobs, setJobs] = useState([]);
   const jobsRef = useRef([]);
   const jobsRef = useRef([]);
+  const lastStreamStatus = useRef("");
+  const [hasError, setHasError] = useState(false);
   const [hasPorterImageTemplate, setHasPorterImageTemplate] = useState(true);
   const [hasPorterImageTemplate, setHasPorterImageTemplate] = useState(true);
   const [selectedJob, setSelectedJob] = useState(null);
   const [selectedJob, setSelectedJob] = useState(null);
   const [status, setStatus] = useState<"loading" | "ready">("loading");
   const [status, setStatus] = useState<"loading" | "ready">("loading");
@@ -42,21 +44,12 @@ export const useJobs = (chart: ChartType) => {
   const sortJobsAndSave = (newJobs: any[]) => {
   const sortJobsAndSave = (newJobs: any[]) => {
     // Set job run from URL if needed
     // Set job run from URL if needed
     const urlParams = new URLSearchParams(location.search);
     const urlParams = new URLSearchParams(location.search);
-    const urlJob = urlParams.get("job");
 
 
     const getTime = (job: any) => {
     const getTime = (job: any) => {
       return new Date(job?.status?.startTime).getTime();
       return new Date(job?.status?.startTime).getTime();
     };
     };
 
 
-    newJobs.sort((job1, job2) => {
-      // if (job1.metadata.name === urlJob) {
-      //   this.setJobRun(job1);
-      // } else if (job2.metadata.name === urlJob) {
-      //   this.setJobRun(job2);
-      // }
-
-      return getTime(job2) - getTime(job1);
-    });
+    newJobs.sort((job1, job2) => getTime(job2) - getTime(job1));
 
 
     let latestImageDetected =
     let latestImageDetected =
       newJobs[0]?.spec?.template?.spec?.containers[0]?.image;
       newJobs[0]?.spec?.template?.spec?.containers[0]?.image;
@@ -68,6 +61,23 @@ export const useJobs = (chart: ChartType) => {
     setJobs(newJobs);
     setJobs(newJobs);
   };
   };
 
 
+  const addJob = (newJob: any) => {
+    let newJobs = [...jobsRef.current];
+    const existingJobIndex = newJobs.findIndex((currentJob) => {
+      return (
+        currentJob.metadata?.name === newJob.metadata?.name &&
+        currentJob.metadata?.namespace === newJob.metadata?.namespace
+      );
+    });
+
+    if (existingJobIndex > -1) {
+      return;
+    }
+
+    newJobs.push(newJob);
+    sortJobsAndSave(newJobs);
+  };
+
   const mergeNewJob = (newJob: any) => {
   const mergeNewJob = (newJob: any) => {
     let newJobs = [...jobsRef.current];
     let newJobs = [...jobsRef.current];
     const existingJobIndex = newJobs.findIndex((currentJob) => {
     const existingJobIndex = newJobs.findIndex((currentJob) => {
@@ -183,8 +193,13 @@ export const useJobs = (chart: ChartType) => {
           return;
           return;
         }
         }
 
 
+        if (event.event_type === "ADD") {
+          addJob(event.Object);
+          return;
+        }
+
         // if event type is add or update, merge with existing jobs
         // if event type is add or update, merge with existing jobs
-        if (event.event_type === "ADD" || event.event_type === "UPDATE") {
+        if (event.event_type === "UPDATE") {
           mergeNewJob(event.Object);
           mergeNewJob(event.Object);
           return;
           return;
         }
         }
@@ -216,22 +231,61 @@ export const useJobs = (chart: ChartType) => {
     setSelectedJob(job);
     setSelectedJob(job);
   };
   };
 
 
-  useEffect(() => {
-    let isSubscribed = true;
+  // useEffect(() => {
+  //   let isSubscribed = true;
+
+  //   if (!chart) {
+  //     return () => {
+  //       isSubscribed = false;
+  //     };
+  //   }
+
+  //   if (
+  //     previousChart?.name === chart?.name &&
+  //     previousChart?.namespace === chart?.namespace
+  //   ) {
+  //     return () => {
+  //       isSubscribed = false;
+  //     };
+  //   }
+
+  //   setStatus("loading");
+  //   const newestImage = chart?.config?.image?.repository;
+
+  //   setHasPorterImageTemplate(PORTER_IMAGE_TEMPLATES.includes(newestImage));
+
+  //   api
+  //     .getJobs(
+  //       "<token>",
+  //       {},
+  //       {
+  //         id: currentProject?.id,
+  //         cluster_id: currentCluster?.id,
+  //         namespace: chart.namespace,
+  //         release_name: chart.name,
+  //       }
+  //     )
+  //     .then((res) => {
+  //       if (isSubscribed) {
+  //         sortJobsAndSave(res.data);
+  //         setStatus("ready");
+  //       }
+  //     });
+  //   return () => {
+  //     isSubscribed = false;
+  //   };
+  // }, [chart]);
 
 
-    if (!chart) {
-      return () => {
-        isSubscribed = false;
-      };
+  useEffect(() => {
+    if (!chart || !chart.namespace || !chart.name) {
+      return () => {};
     }
     }
 
 
     if (
     if (
       previousChart?.name === chart?.name &&
       previousChart?.name === chart?.name &&
       previousChart?.namespace === chart?.namespace
       previousChart?.namespace === chart?.namespace
     ) {
     ) {
-      return () => {
-        isSubscribed = false;
-      };
+      return () => {};
     }
     }
 
 
     setStatus("loading");
     setStatus("loading");
@@ -239,28 +293,56 @@ export const useJobs = (chart: ChartType) => {
 
 
     setHasPorterImageTemplate(PORTER_IMAGE_TEMPLATES.includes(newestImage));
     setHasPorterImageTemplate(PORTER_IMAGE_TEMPLATES.includes(newestImage));
 
 
-    api
-      .getJobs(
-        "<token>",
-        {},
-        {
-          id: currentProject?.id,
-          cluster_id: currentCluster?.id,
-          namespace: chart.namespace,
-          release_name: chart.name,
-        }
-      )
-      .then((res) => {
-        if (isSubscribed) {
-          sortJobsAndSave(res.data);
+    const namespace = chart.namespace;
+    const release_name = chart.name;
+
+    closeAllWebsockets();
+    jobsRef.current = [];
+    lastStreamStatus.current = "";
+    setJobs([]);
+
+    const websocketId = `job-runs-websocket-${release_name}-${namespace}`;
+
+    const endpoint = `/api/projects/${currentProject.id}/clusters/${currentCluster.id}/namespaces/${namespace}/jobs/stream?name=${release_name}`;
+
+    const config: NewWebsocketOptions = {
+      onopen: console.log,
+      onmessage: (message) => {
+        const data = JSON.parse(message.data);
+
+        if (data.streamStatus === "finished") {
+          setHasError(false);
           setStatus("ready");
           setStatus("ready");
+          sortJobsAndSave(jobsRef.current);
+          lastStreamStatus.current = data.streamStatus;
           setupJobWebsocket();
           setupJobWebsocket();
           setupCronJobWebsocket();
           setupCronJobWebsocket();
+          return;
         }
         }
-      });
-    return () => {
-      isSubscribed = false;
+
+        if (data.streamStatus === "errored") {
+          setHasError(true);
+          jobsRef.current = [];
+          setJobs([]);
+          setStatus("ready");
+          return;
+        }
+
+        jobsRef.current = [...jobsRef.current, data];
+      },
+      onclose: (event) => {
+        console.log(event);
+        closeWebsocket(websocketId);
+      },
+      onerror: (error) => {
+        setHasError(true);
+        setStatus("ready");
+        console.log(error);
+        closeWebsocket(websocketId);
+      },
     };
     };
+    newWebsocket(websocketId, endpoint, config);
+    openWebsocket(websocketId);
   }, [chart]);
   }, [chart]);
 
 
   useEffect(() => {
   useEffect(() => {