Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49a1bd40ff | ||
| f847424b9c | |||
|
|
d50a576e31 | ||
|
|
eba2ad6232 | ||
| 14961cce01 |
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -2,3 +2,8 @@
|
||||
path = knockoutwhist
|
||||
branch = main
|
||||
url = https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist.git
|
||||
|
||||
[submodule "knockoutwhistfrontend"]
|
||||
path = knockoutwhistfrontend
|
||||
branch = main
|
||||
url = https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend.git
|
||||
|
||||
@@ -197,3 +197,10 @@
|
||||
### Features
|
||||
|
||||
* **ui:** FRO-7 Endscreen ([#97](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/issues/97)) ([d57e6ef](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/d57e6efa985ca07c32f9f54595fe7393dbdf4d8a))
|
||||
## (2025-12-03)
|
||||
## (2025-12-03)
|
||||
## (2025-12-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* BAC-25 Race Condition: Websocket Promises ([#99](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/issues/99)) ([f847424](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/f847424b9cea423ace5661d1efb6e4f01483c655))
|
||||
|
||||
1
knockoutwhistfrontend
Submodule
1
knockoutwhistfrontend
Submodule
Submodule knockoutwhistfrontend added at 575d1b5e8e
@@ -26,6 +26,7 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
|
||||
else canInteract = Some(InteractionType.Card)
|
||||
case _ =>
|
||||
}
|
||||
websocketActor.foreach(_.solveRequests())
|
||||
websocketActor.foreach(_.transmitEventToClient(event))
|
||||
}
|
||||
|
||||
@@ -38,8 +39,6 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
|
||||
}
|
||||
|
||||
def handleWebResponse(eventType: String, data: JsObject): Unit = {
|
||||
lock.lock()
|
||||
val result = Try {
|
||||
eventType match {
|
||||
case "ping" =>
|
||||
// No action needed for Ping
|
||||
@@ -77,11 +76,5 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
|
||||
gameLobby.returnToLobby(this)
|
||||
}
|
||||
}
|
||||
lock.unlock()
|
||||
if (result.isFailure) {
|
||||
val throwable = result.failed.get
|
||||
throw throwable
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.apache.pekko.actor.{Actor, ActorRef}
|
||||
import play.api.libs.json.{JsObject, JsValue, Json}
|
||||
import util.WebsocketEventMapper
|
||||
|
||||
import scala.collection.mutable
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class UserWebsocketActor(
|
||||
@@ -12,6 +13,8 @@ class UserWebsocketActor(
|
||||
session: UserSession
|
||||
) extends Actor {
|
||||
|
||||
private val requests: mutable.Map[String, String] = mutable.Map()
|
||||
|
||||
{
|
||||
session.lock.lock()
|
||||
if (session.websocketActor.isDefined) {
|
||||
@@ -48,12 +51,14 @@ class UserWebsocketActor(
|
||||
}
|
||||
|
||||
private def handle(json: JsValue): Unit = {
|
||||
session.lock.lock()
|
||||
val idOpt = (json \ "id").asOpt[String]
|
||||
if (idOpt.isEmpty) {
|
||||
transmitJsonToClient(Json.obj(
|
||||
"status" -> "error",
|
||||
"error" -> "Missing 'id' field"
|
||||
))
|
||||
session.lock.unlock()
|
||||
return
|
||||
}
|
||||
val id = idOpt.get
|
||||
@@ -65,17 +70,25 @@ class UserWebsocketActor(
|
||||
"status" -> "error",
|
||||
"error" -> "Missing 'event' field"
|
||||
))
|
||||
session.lock.unlock()
|
||||
return
|
||||
}
|
||||
val statusOpt = (json \ "status").asOpt[String]
|
||||
if (statusOpt.isDefined) {
|
||||
session.lock.unlock()
|
||||
return
|
||||
}
|
||||
val event = eventOpt.get
|
||||
val data = (json \ "data").asOpt[JsObject].getOrElse(Json.obj())
|
||||
requests += (id -> event)
|
||||
val result = Try {
|
||||
session.handleWebResponse(event, data)
|
||||
}
|
||||
if (!requests.contains(id)) {
|
||||
session.lock.unlock()
|
||||
return
|
||||
}
|
||||
requests -= id
|
||||
if (result.isSuccess) {
|
||||
transmitJsonToClient(Json.obj(
|
||||
"id" -> id,
|
||||
@@ -90,6 +103,7 @@ class UserWebsocketActor(
|
||||
"error" -> result.failed.get.getMessage
|
||||
))
|
||||
}
|
||||
session.lock.unlock()
|
||||
}
|
||||
|
||||
def transmitJsonToClient(jsonObj: JsValue): Unit = {
|
||||
@@ -100,4 +114,20 @@ class UserWebsocketActor(
|
||||
transmitJsonToClient(WebsocketEventMapper.toJson(event, session))
|
||||
}
|
||||
|
||||
def solveRequests(): Unit = {
|
||||
if (!session.lock.isHeldByCurrentThread)
|
||||
return;
|
||||
if (requests.isEmpty)
|
||||
return;
|
||||
val pendingRequests = requests.toMap
|
||||
requests.clear()
|
||||
pendingRequests.foreach { case (id, event) =>
|
||||
transmitJsonToClient(Json.obj(
|
||||
"id" -> id,
|
||||
"event" -> event,
|
||||
"status" -> "success"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
MAJOR=4
|
||||
MINOR=7
|
||||
PATCH=0
|
||||
PATCH=3
|
||||
|
||||
Reference in New Issue
Block a user