CommandStreamChannel block the duplicate call

add GameCommandHandlerTest
Create a CommandStreamChannelBuilder to inject maxCacheTime
Add missing empty disabled test
fix EventStreamInMemory.readAll
This commit is contained in:
2025-03-11 21:40:16 +01:00
parent 0fbea7903a
commit c84aa7e0c1
22 changed files with 282 additions and 90 deletions

View File

@@ -1,6 +1,7 @@
package eventDemo.app.query
import eventDemo.app.command.GameCommandHandler
import eventDemo.app.command.command.GameCommand
import eventDemo.app.command.command.IWantToJoinTheGameCommand
import eventDemo.app.command.command.IWantToPlayCardCommand
import eventDemo.app.command.command.IamReadyToPlayCommand
@@ -14,20 +15,16 @@ import eventDemo.app.event.projection.buildStateFromEventStream
import eventDemo.app.eventListener.GameEventPlayerNotificationListener
import eventDemo.app.eventListener.GameEventReactionListener
import eventDemo.app.notification.ItsTheTurnOfNotification
import eventDemo.app.notification.Notification
import eventDemo.app.notification.PlayerAsJoinTheGameNotification
import eventDemo.app.notification.PlayerAsPlayACardNotification
import eventDemo.app.notification.PlayerWasReadyNotification
import eventDemo.app.notification.TheGameWasStartedNotification
import eventDemo.app.notification.WelcomeToTheGameNotification
import eventDemo.configuration.appKoinModule
import eventDemo.libs.fromFrameChannel
import eventDemo.libs.toObjectChannel
import eventDemo.shared.toFrame
import eventDemo.shared.toNotification
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.equals.shouldBeEqual
import io.ktor.websocket.Frame
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
@@ -48,46 +45,46 @@ class GameStateTest :
val id = GameId()
val player1 = Player(name = "Nikola")
val player2 = Player(name = "Einstein")
val channelCommand1 = Channel<Frame>(Channel.BUFFERED)
val channelCommand2 = Channel<Frame>(Channel.BUFFERED)
val channelNotification1 = Channel<Frame>(Channel.BUFFERED)
val channelNotification2 = Channel<Frame>(Channel.BUFFERED)
val channelCommand1 = Channel<GameCommand>(Channel.BUFFERED)
val channelCommand2 = Channel<GameCommand>(Channel.BUFFERED)
val channelNotification1 = Channel<Notification>(Channel.BUFFERED)
val channelNotification2 = Channel<Notification>(Channel.BUFFERED)
var playedCard1: Card? = null
var playedCard2: Card? = null
val player1Job =
launch {
channelCommand1.send(IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(id, player1)).toFrame())
channelNotification1.receive().toNotification().let {
channelCommand1.send(IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(id, player1)))
channelNotification1.receive().let {
assertIs<WelcomeToTheGameNotification>(it).players shouldBeEqual setOf(player1)
}
channelNotification1.receive().toNotification().let {
channelNotification1.receive().let {
assertIs<PlayerAsJoinTheGameNotification>(it).player shouldBeEqual player2
}
channelCommand1.send(IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(id, player1)).toFrame())
channelNotification1.receive().toNotification().let {
channelCommand1.send(IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(id, player1)))
channelNotification1.receive().let {
assertIs<PlayerWasReadyNotification>(it).player shouldBeEqual player2
}
val player1Hand =
channelNotification1.receive().toNotification().let {
channelNotification1.receive().let {
assertIs<TheGameWasStartedNotification>(it).hand shouldHaveSize 7
}
playedCard1 = player1Hand.first()
channelNotification1.receive().toNotification().let {
channelNotification1.receive().let {
assertIs<ItsTheTurnOfNotification>(it).apply {
player shouldBeEqual player1
}
}
channelCommand1.send(IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(id, player1, player1Hand.first())).toFrame())
channelCommand1.send(IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(id, player1, player1Hand.first())))
channelNotification1.receive().toNotification().let {
channelNotification1.receive().let {
assertIs<ItsTheTurnOfNotification>(it).apply {
player shouldBeEqual player2
}
}
channelNotification1.receive().toNotification().let {
channelNotification1.receive().let {
assertIs<PlayerAsPlayACardNotification>(it).apply {
player shouldBeEqual player2
card shouldBeEqual assertNotNull(playedCard2)
@@ -98,24 +95,24 @@ class GameStateTest :
val player2Job =
launch {
delay(100)
channelCommand2.send(IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(id, player2)).toFrame())
channelNotification2.receive().toNotification().let {
channelCommand2.send(IWantToJoinTheGameCommand(IWantToJoinTheGameCommand.Payload(id, player2)))
channelNotification2.receive().let {
assertIs<WelcomeToTheGameNotification>(it).players shouldBeEqual setOf(player1, player2)
}
channelNotification2.receive().toNotification().let {
channelNotification2.receive().let {
assertIs<PlayerWasReadyNotification>(it).player shouldBeEqual player1
}
channelCommand2.send(IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(id, player2)).toFrame())
channelCommand2.send(IamReadyToPlayCommand(IamReadyToPlayCommand.Payload(id, player2)))
val player2Hand =
channelNotification2.receive().toNotification().let {
channelNotification2.receive().let {
assertIs<TheGameWasStartedNotification>(it).hand shouldHaveSize 7
}
channelNotification2.receive().toNotification().let {
channelNotification2.receive().let {
assertIs<ItsTheTurnOfNotification>(it).apply {
player shouldBeEqual player1
}
}
channelNotification2.receive().toNotification().let {
channelNotification2.receive().let {
assertIs<PlayerAsPlayACardNotification>(it).apply {
player shouldBeEqual player1
card shouldBeEqual assertNotNull(playedCard1)
@@ -123,12 +120,12 @@ class GameStateTest :
}
playedCard2 = player2Hand.first()
channelNotification2.receive().toNotification().let {
channelNotification2.receive().let {
assertIs<ItsTheTurnOfNotification>(it).apply {
player shouldBeEqual player2
}
}
channelCommand2.send(IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(id, player2, player2Hand.first())).toFrame())
channelCommand2.send(IWantToPlayCardCommand(IWantToPlayCardCommand.Payload(id, player2, player2Hand.first())))
}
koinApplication { modules(appKoinModule) }.koin.apply {
@@ -140,10 +137,10 @@ class GameStateTest :
playerNotificationListener.startListening(channelNotification2, player2)
GlobalScope.launch(Dispatchers.IO) {
commandHandler.handle(player1, toObjectChannel(channelCommand1), fromFrameChannel(channelNotification1))
commandHandler.handle(player1, channelCommand1, channelNotification1)
}
GlobalScope.launch(Dispatchers.IO) {
commandHandler.handle(player2, toObjectChannel(channelCommand2), fromFrameChannel(channelNotification2))
commandHandler.handle(player2, channelCommand2, channelNotification2)
}
joinAll(player1Job, player2Job)