From 641c892981649eb85640527cc0fe325ff683fa77 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 20 Nov 2025 10:51:39 +0100 Subject: [PATCH] fix(polling): Improve polling mechanism and delay handling (#60) Reviewed-on: https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/pulls/60 --- knockoutwhist | 2 +- .../components/WebApplicationConfiguration.scala | 3 ++- .../app/controllers/IngameController.scala | 3 +-- .../app/controllers/PollingController.scala | 3 ++- knockoutwhistweb/app/logic/game/GameLobby.scala | 9 --------- knockoutwhistweb/app/views/lobby/lobby.scala.html | 2 +- knockoutwhistweb/public/javascripts/main.js | 15 +++++++++------ 7 files changed, 16 insertions(+), 21 deletions(-) diff --git a/knockoutwhist b/knockoutwhist index 372f20c..e432283 160000 --- a/knockoutwhist +++ b/knockoutwhist @@ -1 +1 @@ -Subproject commit 372f20ca6c3308dee21d9fc946689a8fd77cb465 +Subproject commit e4322839d1610ec2f641e2022426408faa2c0aa1 diff --git a/knockoutwhistweb/app/components/WebApplicationConfiguration.scala b/knockoutwhistweb/app/components/WebApplicationConfiguration.scala index 2f13029..e70c069 100644 --- a/knockoutwhistweb/app/components/WebApplicationConfiguration.scala +++ b/knockoutwhistweb/app/components/WebApplicationConfiguration.scala @@ -2,11 +2,12 @@ package components import de.knockoutwhist.components.DefaultConfiguration import de.knockoutwhist.ui.UI +import de.knockoutwhist.utils.DelayHandler import de.knockoutwhist.utils.events.EventListener class WebApplicationConfiguration extends DefaultConfiguration { override def uis: Set[UI] = Set() - override def listener: Set[EventListener] = Set() + override def listener: Set[EventListener] = Set(DelayHandler) } diff --git a/knockoutwhistweb/app/controllers/IngameController.scala b/knockoutwhistweb/app/controllers/IngameController.scala index 7a7afad..ec941a4 100644 --- a/knockoutwhistweb/app/controllers/IngameController.scala +++ b/knockoutwhistweb/app/controllers/IngameController.scala @@ -59,7 +59,6 @@ class IngameController @Inject() ( case Some(g) => val results = Try { returnInnerHTML(g, request.user) - } if (results.isSuccess) { Ok(views.html.main("In-Game - Knockout Whist")(results.get)) @@ -67,7 +66,7 @@ class IngameController @Inject() ( InternalServerError(results.failed.get.getMessage) } case None => - NotFound("Game not found") + Redirect(routes.MainMenuController.mainMenu()) } } def startGame(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] => diff --git a/knockoutwhistweb/app/controllers/PollingController.scala b/knockoutwhistweb/app/controllers/PollingController.scala index 360f2e7..9c69192 100644 --- a/knockoutwhistweb/app/controllers/PollingController.scala +++ b/knockoutwhistweb/app/controllers/PollingController.scala @@ -78,7 +78,8 @@ class PollingController @Inject() ( "name" -> u.name, "id" -> u.id, "self" -> (u.id == userSession.id) - )) + )), + "maxPlayers" -> game.maxPlayers ) } diff --git a/knockoutwhistweb/app/logic/game/GameLobby.scala b/knockoutwhistweb/app/logic/game/GameLobby.scala index c894af5..0e79ad5 100644 --- a/knockoutwhistweb/app/logic/game/GameLobby.scala +++ b/knockoutwhistweb/app/logic/game/GameLobby.scala @@ -119,15 +119,6 @@ class GameLobby private( } } } - - waitingPromises.keys.foreach { playerId => - val queue = eventsPerPlayer(playerId) - if (queue.nonEmpty) { - val promise = waitingPromises(playerId) - promise.success(queue.dequeue()) - waitingPromises.remove(playerId) - } - } } /** diff --git a/knockoutwhistweb/app/views/lobby/lobby.scala.html b/knockoutwhistweb/app/views/lobby/lobby.scala.html index b4d304d..fe124c9 100644 --- a/knockoutwhistweb/app/views/lobby/lobby.scala.html +++ b/knockoutwhistweb/app/views/lobby/lobby.scala.html @@ -14,7 +14,7 @@
-
Playeramount: @gamelobby.getPlayers.size / @gamelobby.maxPlayers
+
Playeramount: @gamelobby.getPlayers.size / @gamelobby.maxPlayers
diff --git a/knockoutwhistweb/public/javascripts/main.js b/knockoutwhistweb/public/javascripts/main.js index c4cb416..1f8f830 100644 --- a/knockoutwhistweb/public/javascripts/main.js +++ b/knockoutwhistweb/public/javascripts/main.js @@ -79,7 +79,13 @@ }) })() +let polling = false; function pollForUpdates(gameId) { + if (polling) { + console.log("[DEBUG] Polling already in progress. Skipping this cycle."); + return; + } + polling = true; console.log(`[DEBUG] Starting poll cycle for Game ID: ${gameId} at ${new Date().toISOString()}`); if (!gameId) { console.error("[DEBUG] Game ID is missing. Stopping poll."); @@ -90,7 +96,7 @@ function pollForUpdates(gameId) { const $mainmenuElement = $('#main-menu-screen') const $mainbody = $('#main-body') if (!$handElement.length && !$lobbyElement.length && !$mainmenuElement.length && !$mainbody.length) { - setTimeout(() => pollForUpdates(gameId), 1000); + setTimeout(() => { polling = false; pollForUpdates(gameId) }, 1000); return; } const route = jsRoutes.controllers.PollingController.polling(gameId); @@ -254,6 +260,7 @@ function pollForUpdates(gameId) { }) } $("#players").html(newHtml); + $('#playerAmount').text(`Playeramount: ${data.users.length} / ${data.maxPlayers}`); } else { console.warn(`[DEBUG] Received unknown status: ${data.status}`); } @@ -267,11 +274,7 @@ function pollForUpdates(gameId) { } }), complete: (() => { - if (!window.location.href.includes("game")) { - console.log("[DEBUG] Page URL changed. Stopping poll restart."); - return; - } - setTimeout(() => pollForUpdates(gameId), 200); + setTimeout(() => { polling = false; pollForUpdates(gameId) }, 200); }) }) }