From 4a9a19631ea950613af44741c7256c247c0e1f52 Mon Sep 17 00:00:00 2001 From: Thomas Cruveilher <38007824+Sorikairox@users.noreply.github.com> Date: Tue, 28 Oct 2025 06:06:12 +0900 Subject: [PATCH] fix(client): do not spam public lobbies requests by waiting for previous request to end before firing a new one (#2276) ## Description: This PR aims to (quickly, not definitely) address https://github.com/openfrontio/OpenFrontIO/issues/2274 as I believe that's an urgent DDOS problem with the frontend design. I am looking at the backend to understand the underlying issue. ## How was this tested: I added a 2 seconds "sleep" to the endpoint `public_lobbies` to simulate loads. The frontend would do request every seconds, which kept piling up on the server and decreased performances, cf screenshot, instead of resolving every 2 seconds, each subsequent request would take longer than the previous one. Screenshot 2025-10-23 at 23 36 37 After adding the fix to the frontend (which can only trigger 1 request at a time, waiting for the previous one), all request completed in approximatively 2 seconds as expected, cf screenshot. Screenshot 2025-10-23 at 23 36 54 ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: sorikairo Co-authored-by: Vivacious Box --- src/client/PublicLobby.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/client/PublicLobby.ts b/src/client/PublicLobby.ts index 3c186be1f..35cd183e6 100644 --- a/src/client/PublicLobby.ts +++ b/src/client/PublicLobby.ts @@ -17,6 +17,7 @@ export class PublicLobby extends LitElement { private currLobby: GameInfo | null = null; private debounceDelay: number = 750; private lobbyIDToStart = new Map(); + private lobbiesFetchInFlight: Promise | null = null; createRenderRoot() { return this; @@ -73,16 +74,26 @@ export class PublicLobby extends LitElement { } async fetchLobbies(): Promise { - try { - const response = await fetch(`/api/public_lobbies`); - if (!response.ok) - throw new Error(`HTTP error! status: ${response.status}`); - const data = await response.json(); - return data.lobbies; - } catch (error) { - console.error("Error fetching lobbies:", error); - throw error; + if (this.lobbiesFetchInFlight) { + return this.lobbiesFetchInFlight; } + + this.lobbiesFetchInFlight = (async () => { + try { + const response = await fetch(`/api/public_lobbies`); + if (!response.ok) + throw new Error(`HTTP error! status: ${response.status}`); + const data = await response.json(); + return data.lobbies as GameInfo[]; + } catch (error) { + console.error("Error fetching lobbies:", error); + throw error; + } finally { + this.lobbiesFetchInFlight = null; + } + })(); + + return this.lobbiesFetchInFlight; } public stop() {