Compare commits
2 Commits
4.7.3
...
ead79cf355
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ead79cf355 | ||
|
|
a0df05e417 |
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -2,8 +2,3 @@
|
|||||||
path = knockoutwhist
|
path = knockoutwhist
|
||||||
branch = main
|
branch = main
|
||||||
url = https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist.git
|
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
|
|
||||||
|
|||||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -192,15 +192,3 @@
|
|||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* FRO-6 Websocket Close Handle ([#96](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/issues/96)) ([3585566](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/358556612ec74601c8b31125e4e65f750abf8c4c))
|
* FRO-6 Websocket Close Handle ([#96](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/issues/96)) ([3585566](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/358556612ec74601c8b31125e4e65f750abf8c4c))
|
||||||
## (2025-12-03)
|
|
||||||
|
|
||||||
### 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))
|
|
||||||
|
|||||||
Submodule knockoutwhistfrontend deleted from 575d1b5e8e
@@ -26,7 +26,6 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
|
|||||||
else canInteract = Some(InteractionType.Card)
|
else canInteract = Some(InteractionType.Card)
|
||||||
case _ =>
|
case _ =>
|
||||||
}
|
}
|
||||||
websocketActor.foreach(_.solveRequests())
|
|
||||||
websocketActor.foreach(_.transmitEventToClient(event))
|
websocketActor.foreach(_.transmitEventToClient(event))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +38,8 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
def handleWebResponse(eventType: String, data: JsObject): Unit = {
|
def handleWebResponse(eventType: String, data: JsObject): Unit = {
|
||||||
|
lock.lock()
|
||||||
|
val result = Try {
|
||||||
eventType match {
|
eventType match {
|
||||||
case "ping" =>
|
case "ping" =>
|
||||||
// No action needed for Ping
|
// No action needed for Ping
|
||||||
@@ -76,5 +77,11 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
|
|||||||
gameLobby.returnToLobby(this)
|
gameLobby.returnToLobby(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lock.unlock()
|
||||||
|
if (result.isFailure) {
|
||||||
|
val throwable = result.failed.get
|
||||||
|
throw throwable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import org.apache.pekko.actor.{Actor, ActorRef}
|
|||||||
import play.api.libs.json.{JsObject, JsValue, Json}
|
import play.api.libs.json.{JsObject, JsValue, Json}
|
||||||
import util.WebsocketEventMapper
|
import util.WebsocketEventMapper
|
||||||
|
|
||||||
import scala.collection.mutable
|
|
||||||
import scala.util.{Failure, Success, Try}
|
import scala.util.{Failure, Success, Try}
|
||||||
|
|
||||||
class UserWebsocketActor(
|
class UserWebsocketActor(
|
||||||
@@ -13,8 +12,6 @@ class UserWebsocketActor(
|
|||||||
session: UserSession
|
session: UserSession
|
||||||
) extends Actor {
|
) extends Actor {
|
||||||
|
|
||||||
private val requests: mutable.Map[String, String] = mutable.Map()
|
|
||||||
|
|
||||||
{
|
{
|
||||||
session.lock.lock()
|
session.lock.lock()
|
||||||
if (session.websocketActor.isDefined) {
|
if (session.websocketActor.isDefined) {
|
||||||
@@ -51,14 +48,12 @@ class UserWebsocketActor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def handle(json: JsValue): Unit = {
|
private def handle(json: JsValue): Unit = {
|
||||||
session.lock.lock()
|
|
||||||
val idOpt = (json \ "id").asOpt[String]
|
val idOpt = (json \ "id").asOpt[String]
|
||||||
if (idOpt.isEmpty) {
|
if (idOpt.isEmpty) {
|
||||||
transmitJsonToClient(Json.obj(
|
transmitJsonToClient(Json.obj(
|
||||||
"status" -> "error",
|
"status" -> "error",
|
||||||
"error" -> "Missing 'id' field"
|
"error" -> "Missing 'id' field"
|
||||||
))
|
))
|
||||||
session.lock.unlock()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val id = idOpt.get
|
val id = idOpt.get
|
||||||
@@ -70,25 +65,17 @@ class UserWebsocketActor(
|
|||||||
"status" -> "error",
|
"status" -> "error",
|
||||||
"error" -> "Missing 'event' field"
|
"error" -> "Missing 'event' field"
|
||||||
))
|
))
|
||||||
session.lock.unlock()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val statusOpt = (json \ "status").asOpt[String]
|
val statusOpt = (json \ "status").asOpt[String]
|
||||||
if (statusOpt.isDefined) {
|
if (statusOpt.isDefined) {
|
||||||
session.lock.unlock()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val event = eventOpt.get
|
val event = eventOpt.get
|
||||||
val data = (json \ "data").asOpt[JsObject].getOrElse(Json.obj())
|
val data = (json \ "data").asOpt[JsObject].getOrElse(Json.obj())
|
||||||
requests += (id -> event)
|
|
||||||
val result = Try {
|
val result = Try {
|
||||||
session.handleWebResponse(event, data)
|
session.handleWebResponse(event, data)
|
||||||
}
|
}
|
||||||
if (!requests.contains(id)) {
|
|
||||||
session.lock.unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
requests -= id
|
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
transmitJsonToClient(Json.obj(
|
transmitJsonToClient(Json.obj(
|
||||||
"id" -> id,
|
"id" -> id,
|
||||||
@@ -103,7 +90,6 @@ class UserWebsocketActor(
|
|||||||
"error" -> result.failed.get.getMessage
|
"error" -> result.failed.get.getMessage
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
session.lock.unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def transmitJsonToClient(jsonObj: JsValue): Unit = {
|
def transmitJsonToClient(jsonObj: JsValue): Unit = {
|
||||||
@@ -114,20 +100,4 @@ class UserWebsocketActor(
|
|||||||
transmitJsonToClient(WebsocketEventMapper.toJson(event, session))
|
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
|
MAJOR=4
|
||||||
MINOR=7
|
MINOR=6
|
||||||
PATCH=3
|
PATCH=2
|
||||||
|
|||||||
Reference in New Issue
Block a user