commit c641d7154dbc7bddee80c28cb0efc7dc81c44782
parent ee6104a0c85442b96e095f9cb62b22dd01c3203f
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date: Sat, 28 Sep 2024 13:26:10 +0200
feat(api): handle no response 204
Diffstat:
2 files changed, 53 insertions(+), 39 deletions(-)
diff --git a/src/api/server.cjs b/src/api/server.cjs
@@ -253,7 +253,8 @@ server.on('request', async (req, res) => {
const startlist = await db.distinctStartlist(input.heat_ids);
if (startlist.length < 1) {
- throw new Error("Startlist not found")
+ noContent(res);
+ return
}
res.end(JSON.stringify({
message: 'Distinct athletes for multiple heats',
@@ -297,7 +298,6 @@ server.on('request', async (req, res) => {
}).on('end', async () => {
const b = Buffer.concat(body);
try {
- await verifyToken(req, token)
if (b.length < 1) {
throw new Error("Empty request body")
}
@@ -311,7 +311,8 @@ server.on('request', async (req, res) => {
)
if (scores.length < 1) {
- throw new Error("No scores found")
+ noContent(res);
+ return
}
res.end(JSON.stringify({
message: 'Scores for heat and athlete',
@@ -328,7 +329,6 @@ server.on('request', async (req, res) => {
}).on('end', async () => {
const b = Buffer.concat(body);
try {
- await verifyToken(req, token)
if (b.length < 1) {
throw new Error("Empty request body")
}
@@ -342,7 +342,8 @@ server.on('request', async (req, res) => {
)
if (summary.length < 1) {
- throw new Error("Score summary not found")
+ noContent(res);
+ return
}
res.end(JSON.stringify({
message: 'Score summary for heat and athlete',
@@ -669,6 +670,11 @@ async function verifyToken(req, token) {
return user
}
+function noContent(res) {
+ console.warn('x Warning: 204 no rice 😱');
+ res.statusCode = 204;
+ res.end();
+}
function notFound(res, path) {
console.error('x Error: 404 not found');
res.statusCode = 404;
diff --git a/src/frontend/Leaderboard.jsx b/src/frontend/Leaderboard.jsx
@@ -10,6 +10,7 @@ const ws_port = import.meta.env.VITE_WS_PORT
// use a socket for the real-time leaderboard data
let socket = new WebSocket(`${ws_uri}:${ws_port}/v1/leaderboard`);
+console.info("Attached to server websocket");
export async function addAthleteToHeat(athlete, heat) {
const res = await fetch(`${api_uri}:${api_port}/v1/leaderboard/addAthleteToHeat`, {
@@ -35,11 +36,16 @@ export async function getStartlistForHeats(heatIds) {
"heat_ids": heatIds,
}),
})
- const { data, error } = await res.json()
- if (error) {
- throw error
+ if (res.status === 204) {
+ // return empty startlist
+ return []
+ } else {
+ const { data, error } = await res.json()
+ if (error) {
+ throw error
+ }
+ return data
}
- return data
}
async function getScoresForHeatAndAthlete(heatId, athleteId) {
@@ -51,11 +57,13 @@ async function getScoresForHeatAndAthlete(heatId, athleteId) {
"athlete": athleteId,
}),
})
- const { data, error } = await res.json()
- if (error) {
- throw error
+ if (res.status !== 204) {
+ const { data, error } = await res.json()
+ if (error) {
+ throw error
+ }
+ return data
}
- return data
}
async function getScoreSummaryForHeatAndAthlete(heatId, athleteId) {
@@ -67,24 +75,18 @@ async function getScoreSummaryForHeatAndAthlete(heatId, athleteId) {
"athlete": athleteId,
}),
})
- const { data, error } = await res.json()
- if (error) {
- throw error
+ if (res.status !== 204) {
+ const { data, error } = await res.json()
+ if (error) {
+ throw error
+ }
+ return data
}
- return data
}
async function getScoreSummary(heatIds) {
const startListWithScores = []
-
- let startlist = undefined
- try {
- startlist = await getStartlistForHeats(heatIds)
- } catch (error) {
- console.error(error)
- // fail silently & return empty startlist in case of errors
- return []
- }
+ const startlist = await getStartlistForHeats(heatIds)
for (const i of startlist) {
i.heats = []
@@ -93,16 +95,16 @@ async function getScoreSummary(heatIds) {
try {
// this is an array, because the athlete can be scored by multiple judges
const scores = await getScoresForHeatAndAthlete(h, i.athlete)
- const { score_summary } = await getScoreSummaryForHeatAndAthlete(h, i.athlete)
-
- // add heat results of athlete to startlist entry
- i.heats.push({
- heatId: h,
- scores: scores,
- summary: score_summary
- })
+ const summary = await getScoreSummaryForHeatAndAthlete(h, i.athlete)
+ if (scores && summary) {
+ // add heat results of athlete to startlist entry
+ i.heats.push({
+ heatId: h,
+ scores: scores,
+ summary: summary.score_summary
+ })
+ }
} catch (error) {
- // else don't push any heats (fail silently)
console.error(error)
}
@@ -311,15 +313,21 @@ function Leaderboard({session}) {
useEffect(() => {
(async() => {
- // subscribe to scoring from judges
- socket.send(JSON.stringify({
- method: "watchScores",
- }))
socket.onmessage = async function(event) {
// todo: reload only required scores
const scoreSummary = await getScoreSummary(heatSelection.map(h => h.value))
setLeaderboard(scoreSummary)
}
+ socket.onclose = async function(event) {
+ console.info("Server removed us from client list, reattaching socket");
+ socket = new WebSocket(`${ws_uri}:${ws_port}/v1/leaderboard`);
+ }
+ socket.onopen = function (event) {
+ // subscribe to scoring from judges when socket is opened
+ socket.send(JSON.stringify({
+ method: "watchScores",
+ }))
+ }
setLoading(false)
})();
}, [heatSelection]);