create GameCommandRunner to extract business logic
This commit is contained in:
29
src/main/kotlin/eventDemo/app/command/ErrorNotifier.kt
Normal file
29
src/main/kotlin/eventDemo/app/command/ErrorNotifier.kt
Normal file
@@ -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<Notification>,
|
||||||
|
): 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,8 @@
|
|||||||
package eventDemo.app.command
|
package eventDemo.app.command
|
||||||
|
|
||||||
import eventDemo.app.command.command.GameCommand
|
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.entity.Player
|
||||||
import eventDemo.app.event.GameEventHandler
|
|
||||||
import eventDemo.app.event.event.GameEvent
|
import eventDemo.app.event.event.GameEvent
|
||||||
import eventDemo.app.event.projection.GameStateRepository
|
|
||||||
import eventDemo.app.notification.ErrorNotification
|
|
||||||
import eventDemo.app.notification.Notification
|
import eventDemo.app.notification.Notification
|
||||||
import eventDemo.libs.command.CommandStreamChannelBuilder
|
import eventDemo.libs.command.CommandStreamChannelBuilder
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
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.
|
* This action can be executing an action and produce a new [GameEvent] after verification.
|
||||||
*/
|
*/
|
||||||
class GameCommandHandler(
|
class GameCommandHandler(
|
||||||
private val eventHandler: GameEventHandler,
|
|
||||||
private val gameStateRepository: GameStateRepository,
|
|
||||||
private val commandStreamChannel: CommandStreamChannelBuilder<GameCommand>,
|
private val commandStreamChannel: CommandStreamChannelBuilder<GameCommand>,
|
||||||
|
private val runner: GameCommandRunner,
|
||||||
) {
|
) {
|
||||||
private val logger = KotlinLogging.logger { }
|
private val logger = KotlinLogging.logger { }
|
||||||
|
|
||||||
@@ -48,30 +40,7 @@ class GameCommandHandler(
|
|||||||
message = "Handle command: $command"
|
message = "Handle command: $command"
|
||||||
payload = mapOf("command" to command)
|
payload = mapOf("command" to command)
|
||||||
}
|
}
|
||||||
command.run(outgoingErrorChannelNotification)
|
runner.run(command, outgoingErrorChannelNotification)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun GameCommand.run(outgoingErrorChannelNotification: SendChannel<Notification>) {
|
|
||||||
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<Notification>): 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)
|
|
||||||
}
|
|
||||||
|
|||||||
31
src/main/kotlin/eventDemo/app/command/GameCommandRunner.kt
Normal file
31
src/main/kotlin/eventDemo/app/command/GameCommandRunner.kt
Normal file
@@ -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<Notification>,
|
||||||
|
) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package eventDemo.app.command.command
|
package eventDemo.app.command.command
|
||||||
|
|
||||||
|
import eventDemo.app.command.ErrorNotifier
|
||||||
import eventDemo.app.entity.GameId
|
import eventDemo.app.entity.GameId
|
||||||
import eventDemo.app.entity.Player
|
import eventDemo.app.entity.Player
|
||||||
import eventDemo.app.event.GameEventHandler
|
import eventDemo.app.event.GameEventHandler
|
||||||
@@ -25,7 +26,7 @@ data class ICantPlayCommand(
|
|||||||
|
|
||||||
suspend fun run(
|
suspend fun run(
|
||||||
state: GameState,
|
state: GameState,
|
||||||
playerErrorNotifier: suspend (String) -> Unit,
|
playerErrorNotifier: ErrorNotifier,
|
||||||
eventHandler: GameEventHandler,
|
eventHandler: GameEventHandler,
|
||||||
) {
|
) {
|
||||||
if (state.currentPlayerTurn != payload.player) {
|
if (state.currentPlayerTurn != payload.player) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package eventDemo.app.command.command
|
package eventDemo.app.command.command
|
||||||
|
|
||||||
|
import eventDemo.app.command.ErrorNotifier
|
||||||
import eventDemo.app.entity.GameId
|
import eventDemo.app.entity.GameId
|
||||||
import eventDemo.app.entity.Player
|
import eventDemo.app.entity.Player
|
||||||
import eventDemo.app.event.GameEventHandler
|
import eventDemo.app.event.GameEventHandler
|
||||||
@@ -26,7 +27,7 @@ data class IWantToJoinTheGameCommand(
|
|||||||
|
|
||||||
suspend fun run(
|
suspend fun run(
|
||||||
state: GameState,
|
state: GameState,
|
||||||
playerErrorNotifier: suspend (String) -> Unit,
|
playerErrorNotifier: ErrorNotifier,
|
||||||
eventHandler: GameEventHandler,
|
eventHandler: GameEventHandler,
|
||||||
) {
|
) {
|
||||||
val logger = KotlinLogging.logger {}
|
val logger = KotlinLogging.logger {}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package eventDemo.app.command.command
|
package eventDemo.app.command.command
|
||||||
|
|
||||||
|
import eventDemo.app.command.ErrorNotifier
|
||||||
import eventDemo.app.entity.Card
|
import eventDemo.app.entity.Card
|
||||||
import eventDemo.app.entity.GameId
|
import eventDemo.app.entity.GameId
|
||||||
import eventDemo.app.entity.Player
|
import eventDemo.app.entity.Player
|
||||||
@@ -27,7 +28,7 @@ data class IWantToPlayCardCommand(
|
|||||||
|
|
||||||
suspend fun run(
|
suspend fun run(
|
||||||
state: GameState,
|
state: GameState,
|
||||||
playerErrorNotifier: suspend (String) -> Unit,
|
playerErrorNotifier: ErrorNotifier,
|
||||||
eventHandler: GameEventHandler,
|
eventHandler: GameEventHandler,
|
||||||
) {
|
) {
|
||||||
if (!state.isStarted) {
|
if (!state.isStarted) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package eventDemo.app.command.command
|
package eventDemo.app.command.command
|
||||||
|
|
||||||
|
import eventDemo.app.command.ErrorNotifier
|
||||||
import eventDemo.app.entity.GameId
|
import eventDemo.app.entity.GameId
|
||||||
import eventDemo.app.entity.Player
|
import eventDemo.app.entity.Player
|
||||||
import eventDemo.app.event.GameEventHandler
|
import eventDemo.app.event.GameEventHandler
|
||||||
@@ -25,7 +26,7 @@ data class IamReadyToPlayCommand(
|
|||||||
|
|
||||||
suspend fun run(
|
suspend fun run(
|
||||||
state: GameState,
|
state: GameState,
|
||||||
playerErrorNotifier: suspend (String) -> Unit,
|
playerErrorNotifier: ErrorNotifier,
|
||||||
eventHandler: GameEventHandler,
|
eventHandler: GameEventHandler,
|
||||||
) {
|
) {
|
||||||
val playerExist: Boolean = state.players.contains(payload.player)
|
val playerExist: Boolean = state.players.contains(payload.player)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package eventDemo.configuration
|
package eventDemo.configuration
|
||||||
|
|
||||||
import eventDemo.app.command.GameCommandHandler
|
import eventDemo.app.command.GameCommandHandler
|
||||||
|
import eventDemo.app.command.GameCommandRunner
|
||||||
import eventDemo.app.command.command.GameCommand
|
import eventDemo.app.command.command.GameCommand
|
||||||
import eventDemo.app.event.GameEventBus
|
import eventDemo.app.event.GameEventBus
|
||||||
import eventDemo.app.event.GameEventHandler
|
import eventDemo.app.event.GameEventHandler
|
||||||
@@ -40,6 +41,7 @@ val appKoinModule =
|
|||||||
}
|
}
|
||||||
|
|
||||||
singleOf(::GameEventHandler)
|
singleOf(::GameEventHandler)
|
||||||
|
singleOf(::GameCommandRunner)
|
||||||
singleOf(::GameCommandHandler)
|
singleOf(::GameCommandHandler)
|
||||||
singleOf(::PlayerNotificationEventListener)
|
singleOf(::PlayerNotificationEventListener)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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") { }
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user