summaryrefslogtreecommitdiff
path: root/sw-ui-kt
diff options
context:
space:
mode:
authorJoffrey Bion <joffrey.bion@booking.com>2020-03-26 10:51:41 +0100
committerJoffrey Bion <joffrey.bion@booking.com>2020-03-27 10:59:39 +0100
commitaaaf2d4880b649eda35c96abfaa68976cf023d6f (patch)
tree244f6f1db0a1f15ff8b71128e9fb08fe279af022 /sw-ui-kt
parentAdd more functions to sagas framework (diff)
downloadseven-wonders-aaaf2d4880b649eda35c96abfaa68976cf023d6f.tar.gz
seven-wonders-aaaf2d4880b649eda35c96abfaa68976cf023d6f.tar.bz2
seven-wonders-aaaf2d4880b649eda35c96abfaa68976cf023d6f.zip
Properly unsubscribe from server in GameBrowser sagas
Diffstat (limited to 'sw-ui-kt')
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt2
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt7
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt60
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt14
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/utils/CoroutinesUtils.kt17
5 files changed, 53 insertions, 47 deletions
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt
index 27c451be..e5c2b13e 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Actions.kt
@@ -13,7 +13,7 @@ data class UpdateGameListAction(val games: List<LobbyDTO>): RAction
data class UpdateLobbyAction(val lobby: LobbyDTO): RAction
-data class EnterLobbyAction(val gameId: Long): RAction
+data class EnterLobbyAction(val lobby: LobbyDTO): RAction
data class UpdatePlayers(val players: Map<String, PlayerDTO>): RAction
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt
index 69941c91..4c75bd66 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/Reducers.kt
@@ -27,13 +27,14 @@ private fun currentPlayerReducer(username: String?, action: RAction): String? =
else -> username
}
-private fun currentLobbyReducer(currentLobby: Long?, action: RAction): Long? = when (action) {
- is EnterLobbyAction -> action.gameId
- else -> currentLobby
+private fun currentLobbyReducer(currentLobbyId: Long?, action: RAction): Long? = when (action) {
+ is EnterLobbyAction -> action.lobby.id
+ else -> currentLobbyId
}
private fun gamesReducer(games: Map<Long, LobbyDTO>, action: RAction): Map<Long, LobbyDTO> = when (action) {
is UpdateGameListAction -> action.games.associateBy { it.id } // replaces because should remove deleted games
+ is EnterLobbyAction -> games + (action.lobby.id to action.lobby)
is UpdateLobbyAction -> games + (action.lobby.id to action.lobby)
else -> games
}
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt
index f2dd4e0f..c5e3bdb8 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/GameBrowserSagas.kt
@@ -1,57 +1,47 @@
package org.luxons.sevenwonders.ui.redux.sagas
+import com.palantir.blueprintjs.org.luxons.sevenwonders.ui.utils.awaitFirst
import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
+import org.hildan.krossbow.stomp.StompSubscription
import org.luxons.sevenwonders.client.SevenWondersSession
import org.luxons.sevenwonders.model.api.LobbyDTO
import org.luxons.sevenwonders.ui.redux.EnterLobbyAction
import org.luxons.sevenwonders.ui.redux.RequestCreateGameAction
import org.luxons.sevenwonders.ui.redux.RequestJoinGameAction
import org.luxons.sevenwonders.ui.redux.UpdateGameListAction
-import org.luxons.sevenwonders.ui.redux.UpdateLobbyAction
-import org.luxons.sevenwonders.ui.router.Router
-import kotlin.coroutines.coroutineContext
suspend fun SwSagaContext.gameBrowserSaga(session: SevenWondersSession) {
- coroutineScope {
- launch { watchGames(session) }
- launch { watchCreateGame(session) }
- launch { watchJoinGame(session) }
- }
+ GameBrowserSaga(session, this).run()
}
-private suspend fun SwSagaContext.watchGames(session: SevenWondersSession) {
- val gamesSubscription = session.watchGames()
- for (lobbies in gamesSubscription.messages) {
- if (!coroutineContext.isActive) {
+private class GameBrowserSaga(
+ private val session: SevenWondersSession,
+ private val sagaContext: SwSagaContext
+) {
+ suspend fun run() {
+ coroutineScope {
+ val gamesSubscription = session.watchGames()
+ launch { dispatchGameUpdates(gamesSubscription) }
+ val lobby = awaitCreateOrJoinGame()
gamesSubscription.unsubscribe()
- break
+ sagaContext.dispatch(EnterLobbyAction(lobby))
}
- dispatch(UpdateGameListAction(lobbies.toList()))
}
-}
-private suspend fun SwSagaContext.watchCreateGame(session: SevenWondersSession) =
- onEach<RequestCreateGameAction> {
- val lobby = session.createGame(it.gameName)
- handleGameJoined(session, lobby)
- }
+ private suspend fun dispatchGameUpdates(gamesSubscription: StompSubscription<List<LobbyDTO>>) {
+ sagaContext.dispatchAll(gamesSubscription.messages) { UpdateGameListAction(it) }
+ }
-private suspend fun SwSagaContext.watchJoinGame(session: SevenWondersSession) =
- onEach<RequestJoinGameAction> {
- val lobby = session.joinGame(it.gameId)
- handleGameJoined(session, lobby)
- }
+ private suspend fun awaitCreateOrJoinGame(): LobbyDTO = awaitFirst(this::awaitCreateGame, this::awaitJoinGame)
-private suspend fun SwSagaContext.handleGameJoined(
- session: SevenWondersSession,
- lobby: LobbyDTO
-) {
- dispatch(UpdateLobbyAction(lobby))
- dispatch(EnterLobbyAction(lobby.id))
- coroutineScope {
- launch { lobbySaga(session, lobby.id) }
- Router.lobby()
+ private suspend fun awaitCreateGame(): LobbyDTO {
+ val action = sagaContext.next<RequestCreateGameAction>()
+ return session.createGame(action.gameName)
+ }
+
+ private suspend fun awaitJoinGame(): LobbyDTO {
+ val action = sagaContext.next<RequestJoinGameAction>()
+ return session.joinGame(action.gameId)
}
}
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt
index 1d15e8c4..ded0bc89 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/redux/sagas/Sagas.kt
@@ -1,7 +1,5 @@
package org.luxons.sevenwonders.ui.redux.sagas
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
import org.luxons.sevenwonders.client.SevenWondersClient
import org.luxons.sevenwonders.ui.redux.RequestChooseName
import org.luxons.sevenwonders.ui.redux.SetCurrentPlayerAction
@@ -17,11 +15,11 @@ suspend fun SwSagaContext.rootSaga() {
val session = SevenWondersClient().connect("localhost:8000")
console.info("Connected to Seven Wonders web socket API")
- coroutineScope {
- launch { gameBrowserSaga(session) }
+ val player = session.chooseName(action.playerName)
+ dispatch(SetCurrentPlayerAction(player))
- val player = session.chooseName(action.playerName)
- dispatch(SetCurrentPlayerAction(player))
- Router.games()
- }
+ Router.games()
+ gameBrowserSaga(session)
+ Router.lobby()
+ lobbySaga(session)
}
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/utils/CoroutinesUtils.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/utils/CoroutinesUtils.kt
new file mode 100644
index 00000000..c7e950c8
--- /dev/null
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/utils/CoroutinesUtils.kt
@@ -0,0 +1,17 @@
+package com.palantir.blueprintjs.org.luxons.sevenwonders.ui.utils
+
+import kotlinx.coroutines.async
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.selects.select
+
+suspend inline fun <R> awaitFirst(
+ crossinline f1: suspend () -> R,
+ crossinline f2: suspend () -> R
+): R = coroutineScope {
+ val deferred1 = async { f1() }
+ val deferred2 = async { f2() }
+ select<R> {
+ deferred1.onAwait { deferred2.cancel(); it }
+ deferred2.onAwait { deferred1.cancel(); it }
+ }
+}
bgstack15