diff --git a/src/main/kotlin/eventDemo/app/command/ErrorNotifier.kt b/src/main/kotlin/eventDemo/app/command/ErrorNotifier.kt new file mode 100644 index 0000000..4515190 --- /dev/null +++ b/src/main/kotlin/eventDemo/app/command/ErrorNotifier.kt @@ -0,0 +1,29 @@ +package eventDemo.app.command + +import eventDemo.app.command.command.GameCommand +import eventDemo.app.notification.ErrorNotification +import eventDemo.app.notification.Notification +import io.github.oshai.kotlinlogging.KotlinLogging +import kotlinx.coroutines.channels.SendChannel + +typealias ErrorNotifier = suspend (String) -> Unit + +fun errorNotifier( + command: GameCommand, + channel: SendChannel, +): ErrorNotifier = + { + val logger = KotlinLogging.logger { } + ErrorNotification(message = it) + .let { notification -> + logger.atWarn { + message = "Notification send ERROR: ${notification.message}" + payload = + mapOf( + "notification" to notification, + "command" to command, + ) + } + channel.send(notification) + } + } diff --git a/src/main/kotlin/eventDemo/app/command/GameCommandHandler.kt b/src/main/kotlin/eventDemo/app/command/GameCommandHandler.kt index a617e7c..5c56c7b 100644 --- a/src/main/kotlin/eventDemo/app/command/GameCommandHandler.kt +++ b/src/main/kotlin/eventDemo/app/command/GameCommandHandler.kt @@ -1,15 +1,8 @@ package eventDemo.app.command import eventDemo.app.command.command.GameCommand -import eventDemo.app.command.command.ICantPlayCommand -import eventDemo.app.command.command.IWantToJoinTheGameCommand -import eventDemo.app.command.command.IWantToPlayCardCommand -import eventDemo.app.command.command.IamReadyToPlayCommand import eventDemo.app.entity.Player -import eventDemo.app.event.GameEventHandler import eventDemo.app.event.event.GameEvent -import eventDemo.app.event.projection.GameStateRepository -import eventDemo.app.notification.ErrorNotification import eventDemo.app.notification.Notification import eventDemo.libs.command.CommandStreamChannelBuilder import io.github.oshai.kotlinlogging.KotlinLogging @@ -22,9 +15,8 @@ import kotlinx.coroutines.channels.SendChannel * This action can be executing an action and produce a new [GameEvent] after verification. */ class GameCommandHandler( - private val eventHandler: GameEventHandler, - private val gameStateRepository: GameStateRepository, private val commandStreamChannel: CommandStreamChannelBuilder, + private val runner: GameCommandRunner, ) { private val logger = KotlinLogging.logger { } @@ -48,30 +40,7 @@ class GameCommandHandler( message = "Handle command: $command" payload = mapOf("command" to command) } - command.run(outgoingErrorChannelNotification) + runner.run(command, outgoingErrorChannelNotification) } } - - private suspend fun GameCommand.run(outgoingErrorChannelNotification: SendChannel) { - val gameState = gameStateRepository.get(payload.gameId) - val playerErrorNotifier = errorNotifier(outgoingErrorChannelNotification) - - when (this) { - is IWantToPlayCardCommand -> run(gameState, playerErrorNotifier, eventHandler) - is IamReadyToPlayCommand -> run(gameState, playerErrorNotifier, eventHandler) - is IWantToJoinTheGameCommand -> run(gameState, playerErrorNotifier, eventHandler) - is ICantPlayCommand -> run(gameState, playerErrorNotifier, eventHandler) - } - } } - -fun errorNotifier(channel: SendChannel): suspend (String) -> Unit = - { - val logger = KotlinLogging.logger { } - val notification = ErrorNotification(message = it) - logger.atWarn { - message = "Notification send ERROR: ${notification.message}" - payload = mapOf("notification" to notification) - } - channel.send(notification) - } diff --git a/src/main/kotlin/eventDemo/app/command/GameCommandRunner.kt b/src/main/kotlin/eventDemo/app/command/GameCommandRunner.kt new file mode 100644 index 0000000..6718df9 --- /dev/null +++ b/src/main/kotlin/eventDemo/app/command/GameCommandRunner.kt @@ -0,0 +1,31 @@ +package eventDemo.app.command + +import eventDemo.app.command.command.GameCommand +import eventDemo.app.command.command.ICantPlayCommand +import eventDemo.app.command.command.IWantToJoinTheGameCommand +import eventDemo.app.command.command.IWantToPlayCardCommand +import eventDemo.app.command.command.IamReadyToPlayCommand +import eventDemo.app.event.GameEventHandler +import eventDemo.app.event.projection.GameStateRepository +import eventDemo.app.notification.Notification +import kotlinx.coroutines.channels.SendChannel + +class GameCommandRunner( + private val eventHandler: GameEventHandler, + private val gameStateRepository: GameStateRepository, +) { + suspend fun run( + command: GameCommand, + outgoingErrorChannelNotification: SendChannel, + ) { + val gameState = gameStateRepository.get(command.payload.gameId) + val errorNotifier = errorNotifier(command, outgoingErrorChannelNotification) + + when (command) { + is IWantToPlayCardCommand -> command.run(gameState, errorNotifier, this.eventHandler) + is IamReadyToPlayCommand -> command.run(gameState, errorNotifier, this.eventHandler) + is IWantToJoinTheGameCommand -> command.run(gameState, errorNotifier, this.eventHandler) + is ICantPlayCommand -> command.run(gameState, errorNotifier, this.eventHandler) + } + } +} diff --git a/src/main/kotlin/eventDemo/app/command/command/ICantPlayCommand.kt b/src/main/kotlin/eventDemo/app/command/command/ICantPlayCommand.kt index 1150ca0..74a4b25 100644 --- a/src/main/kotlin/eventDemo/app/command/command/ICantPlayCommand.kt +++ b/src/main/kotlin/eventDemo/app/command/command/ICantPlayCommand.kt @@ -1,5 +1,6 @@ package eventDemo.app.command.command +import eventDemo.app.command.ErrorNotifier import eventDemo.app.entity.GameId import eventDemo.app.entity.Player import eventDemo.app.event.GameEventHandler @@ -25,7 +26,7 @@ data class ICantPlayCommand( suspend fun run( state: GameState, - playerErrorNotifier: suspend (String) -> Unit, + playerErrorNotifier: ErrorNotifier, eventHandler: GameEventHandler, ) { if (state.currentPlayerTurn != payload.player) { diff --git a/src/main/kotlin/eventDemo/app/command/command/IWantToJoinTheGameCommand.kt b/src/main/kotlin/eventDemo/app/command/command/IWantToJoinTheGameCommand.kt index fe974ff..20305f1 100644 --- a/src/main/kotlin/eventDemo/app/command/command/IWantToJoinTheGameCommand.kt +++ b/src/main/kotlin/eventDemo/app/command/command/IWantToJoinTheGameCommand.kt @@ -1,5 +1,6 @@ package eventDemo.app.command.command +import eventDemo.app.command.ErrorNotifier import eventDemo.app.entity.GameId import eventDemo.app.entity.Player import eventDemo.app.event.GameEventHandler @@ -26,7 +27,7 @@ data class IWantToJoinTheGameCommand( suspend fun run( state: GameState, - playerErrorNotifier: suspend (String) -> Unit, + playerErrorNotifier: ErrorNotifier, eventHandler: GameEventHandler, ) { val logger = KotlinLogging.logger {} diff --git a/src/main/kotlin/eventDemo/app/command/command/IWantToPlayCardCommand.kt b/src/main/kotlin/eventDemo/app/command/command/IWantToPlayCardCommand.kt index a728369..6fd91d7 100644 --- a/src/main/kotlin/eventDemo/app/command/command/IWantToPlayCardCommand.kt +++ b/src/main/kotlin/eventDemo/app/command/command/IWantToPlayCardCommand.kt @@ -1,5 +1,6 @@ package eventDemo.app.command.command +import eventDemo.app.command.ErrorNotifier import eventDemo.app.entity.Card import eventDemo.app.entity.GameId import eventDemo.app.entity.Player @@ -27,7 +28,7 @@ data class IWantToPlayCardCommand( suspend fun run( state: GameState, - playerErrorNotifier: suspend (String) -> Unit, + playerErrorNotifier: ErrorNotifier, eventHandler: GameEventHandler, ) { if (!state.isStarted) { diff --git a/src/main/kotlin/eventDemo/app/command/command/IamReadyToPlayCommand.kt b/src/main/kotlin/eventDemo/app/command/command/IamReadyToPlayCommand.kt index e8b0dd8..28fad91 100644 --- a/src/main/kotlin/eventDemo/app/command/command/IamReadyToPlayCommand.kt +++ b/src/main/kotlin/eventDemo/app/command/command/IamReadyToPlayCommand.kt @@ -1,5 +1,6 @@ package eventDemo.app.command.command +import eventDemo.app.command.ErrorNotifier import eventDemo.app.entity.GameId import eventDemo.app.entity.Player import eventDemo.app.event.GameEventHandler @@ -25,7 +26,7 @@ data class IamReadyToPlayCommand( suspend fun run( state: GameState, - playerErrorNotifier: suspend (String) -> Unit, + playerErrorNotifier: ErrorNotifier, eventHandler: GameEventHandler, ) { val playerExist: Boolean = state.players.contains(payload.player) diff --git a/src/main/kotlin/eventDemo/configuration/ConfigureDI.kt b/src/main/kotlin/eventDemo/configuration/ConfigureDI.kt index e388d26..88083fa 100644 --- a/src/main/kotlin/eventDemo/configuration/ConfigureDI.kt +++ b/src/main/kotlin/eventDemo/configuration/ConfigureDI.kt @@ -1,6 +1,7 @@ package eventDemo.configuration import eventDemo.app.command.GameCommandHandler +import eventDemo.app.command.GameCommandRunner import eventDemo.app.command.command.GameCommand import eventDemo.app.event.GameEventBus import eventDemo.app.event.GameEventHandler @@ -40,6 +41,7 @@ val appKoinModule = } singleOf(::GameEventHandler) + singleOf(::GameCommandRunner) singleOf(::GameCommandHandler) singleOf(::PlayerNotificationEventListener) } diff --git a/src/test/kotlin/eventDemo/app/command/GameCommandRunnerTest.kt b/src/test/kotlin/eventDemo/app/command/GameCommandRunnerTest.kt new file mode 100644 index 0000000..0a17068 --- /dev/null +++ b/src/test/kotlin/eventDemo/app/command/GameCommandRunnerTest.kt @@ -0,0 +1,8 @@ +package eventDemo.app.command + +import io.kotest.core.spec.style.FunSpec + +class GameCommandRunnerTest : + FunSpec({ + test("run should run the correct command") { } + })