Skip to content

Commit

Permalink
Merge pull request #362 from amplimindcc/360-cleanup-sse-properly
Browse files Browse the repository at this point in the history
360 polling
  • Loading branch information
SrNski authored Jun 12, 2024
2 parents 8e59485 + 0e27df8 commit 6723bad
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 83 deletions.
35 changes: 35 additions & 0 deletions src/hooks/useInterval.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useEffect, useRef } from 'react';

type Callback = () => void;

/**
* useInterval custom hook - used similar to useEffect, but for intervals (auto cleanup).
* @author David Linhardt
*
* @param {Callback} callback - callback function
* @param {(number | null)} delay - delay in milliseconds
*/
function useInterval(callback: Callback, delay: number | null): void {
const savedCallback = useRef<Callback | null>(null);

// Remember the latest callback if it changes.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);

// Set up the interval.
useEffect(() => {
function tick() {
if (savedCallback.current) {
savedCallback.current();
}
}

if (delay !== null) {
const id = setInterval(tick, delay);
return () => clearInterval(id); // cleanup
}
}, [delay]);
}

export default useInterval;
3 changes: 1 addition & 2 deletions src/locales/de/admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,5 @@
"setReviewedNotFound": "Die Abgabe mit der E-Mail Adresse {{email}} wurde nicht gefunden.",
"setReviewedUnprocessableEntity": "Die E-Mail Adresse {{email}} ist nicht gültig.",
"setReviewedError": "Ein Fehler ist beim aktiv setzen der Abgabe mit der E-Mail Adresse {{email}} aufgetreten. Bitte versuche es später erneut.",
"errorFetchingChallenges": "Ein Fehler ist beim Abrufen der Challenges aufgetreten. Bitte versuche es später erneut.",
"sseError": "Ein Fehler ist beim Verbinden zum Server aufgetreten ({{event}}). Bitte versuche es später erneut."
"errorFetchingChallenges": "Ein Fehler ist beim Abrufen der Challenges aufgetreten. Bitte versuche es später erneut."
}
3 changes: 1 addition & 2 deletions src/locales/en/admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,5 @@
"setReviewedNotFound": "The submission from email {{email}} could not be found.",
"setReviewedUnprocessableEntity": "The supplied email address {{email}} is not valid.",
"setReviewedError": "An error occurred while trying to set the submission from email {{email}} to reviewed. Please try again later.",
"errorFetchingChallenges": "An error occurred while trying to fetch the challenges. Please try again later.",
"sseError": "An error occurred while trying to establish a connection to the server ({{event}}). Please try again later."
"errorFetchingChallenges": "An error occurred while trying to fetch the challenges. Please try again later."
}
77 changes: 22 additions & 55 deletions src/pages/Admin/components/Submissions/Submissions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { ToastType } from '../../../../interfaces/ToastType';
import moment from 'moment';
import { useAGGridLocaleContext } from '../../../../components/Context/AGGridLocaleContext/useAGGridLocaleContext';
import { StatusCodes } from 'http-status-codes';
import useInterval from '../../../../hooks/useInterval';

const baseURL = import.meta.env.VITE_API_URL;
/**
* Submissions component used in the admin submissions page.
* @author Timo Hauser
Expand All @@ -39,6 +39,7 @@ export default function Submissions() {
*/
const { gridLocale } = useAGGridLocaleContext();

// Refs
/**
* AG Grid Reference
* @author Timo Hauser
Expand All @@ -47,6 +48,15 @@ export default function Submissions() {
*/
const gridRef: LegacyRef<AgGridReact> = useRef<AgGridReact>(null);

// States
/**
* Row Data State
* @author Timo Hauser
*
* @type {UserSubmissionTableElement[]}
*/
const [rowData, setRowData] = useState<UserSubmissionTableElement[]>([]);

/**
* AG Grid Options
* @author Timo Hauser
Expand All @@ -65,60 +75,21 @@ export default function Submissions() {
};

/**
* Row Data State
* get the submission status from the backend on page load
* @author Timo Hauser
*
* @type {UserSubmissionTableElement[]}
*/
const [rowData, setRowData] = useState<UserSubmissionTableElement[]>([]);

useEffect(() => {
/**
* connect SSE to the backend to get the submission status changes in real time and update the table accordingly
* @author Timo Hauser
* @author David Linhardt
*
* @async
* @returns {void}
*/
const connect = async () => {
try {
const res = await submission.heartbeat();
if (!res.ok) {
const data = await res.json();
toast.showToast(
ToastType.ERROR,
toast.httpError(res.status, data.error)
);
} else {
const sse = new EventSource(
`${baseURL}/v1/admin/submission/status/subscribe`,
{ withCredentials: true }
);
sse.addEventListener(
'submission-status-changed',
(event) => {
if (event.data) {
loadSubmissionData();
} else {
console.log('no data');
}
}
);
sse.onerror = () => {
connect();
};
}
} catch (e: unknown) {
toast.showToast(ToastType.ERROR, t('connectionError', { ns: 'main' }));
}
};
connect();
loadSubmissionData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return () => {
// clean up
};
});
/**
* get the submission status from the backend (polling every 4 seconds) using useInterval hook
* @author David Linhardt
*/
useInterval(async () => {
loadSubmissionData();
}, 4000);

/**
* set the state of a submission to reviewed in the backend and update the table afterwards
Expand Down Expand Up @@ -220,10 +191,6 @@ export default function Submissions() {
};
}

useEffect(() => {
loadSubmissionData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
/**
* JSON Submission Item Interface for the backend response data.
* @author Timo Hauser
Expand Down
24 changes: 0 additions & 24 deletions src/services/submission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,29 +86,6 @@ const list = async () => {
return res;
};

/**
* List service : update point for frontend, sends a heartbeat every 15 second
* http://localhost:8080/swagger-ui/index.html#/admin-controller/subscribeToSubmissionStatus
* @author Timo Hauser
*
* @async
* @returns {Promise<Response>} HTTP response
* @throws {any} connection error
*/
const heartbeat = async () => {
const url = `${baseURL}/v1/admin/submission/status/subscribe`;

const res = await fetch(url, {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
});

return res;
};

/**
* Change state service : set the submission state to reviewed, needs email as input
* http://localhost:8080/swagger-ui/index.html#/admin-controller/changeSubmissionStateReviewed
Expand Down Expand Up @@ -182,7 +159,6 @@ export default {
getStatus,
list,
sendSubmission,
heartbeat,
reviewSubmission,
getResultPageLink,
getLinterResult,
Expand Down

0 comments on commit 6723bad

Please sign in to comment.