Create route to list all the games
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package eventDemo.adapter.infrastructureLayer.event.projection
|
||||
|
||||
import eventDemo.business.entity.GameId
|
||||
import eventDemo.business.event.GameEventHandler
|
||||
import eventDemo.business.event.GameEventStore
|
||||
import eventDemo.business.event.projection.gameList.GameList
|
||||
import eventDemo.business.event.projection.gameList.GameListRepository
|
||||
import eventDemo.business.event.projection.gameList.apply
|
||||
import eventDemo.business.event.projection.gameState.GameState
|
||||
import eventDemo.libs.event.projection.ProjectionSnapshotRepositoryInMemory
|
||||
import eventDemo.libs.event.projection.SnapshotConfig
|
||||
|
||||
class GameListRepositoryInMemory(
|
||||
eventStore: GameEventStore,
|
||||
eventHandler: GameEventHandler,
|
||||
snapshotConfig: SnapshotConfig = SnapshotConfig(),
|
||||
) : GameListRepository {
|
||||
private val projectionsSnapshot =
|
||||
ProjectionSnapshotRepositoryInMemory(
|
||||
eventStore = eventStore,
|
||||
snapshotCacheConfig = snapshotConfig,
|
||||
applyToProjection = GameList::apply,
|
||||
initialStateBuilder = { aggregateId: GameId -> GameList(aggregateId) },
|
||||
)
|
||||
|
||||
init {
|
||||
eventHandler.registerProjectionBuilder { event ->
|
||||
projectionsSnapshot.applyAndPutToCache(event)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last version of the [GameState] from the all eventStream.
|
||||
*
|
||||
* It fetches it from the local cache if possible, otherwise it builds it.
|
||||
*/
|
||||
override fun getList(): List<GameList> =
|
||||
projectionsSnapshot.getList()
|
||||
}
|
||||
28
src/main/kotlin/eventDemo/adapter/interfaceLayer/GameList.kt
Normal file
28
src/main/kotlin/eventDemo/adapter/interfaceLayer/GameList.kt
Normal file
@@ -0,0 +1,28 @@
|
||||
package eventDemo.adapter.interfaceLayer
|
||||
|
||||
import eventDemo.business.event.projection.gameList.GameListRepository
|
||||
import io.ktor.resources.Resource
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.auth.authenticate
|
||||
import io.ktor.server.resources.get
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.routing.Route
|
||||
import io.ktor.server.routing.get
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@Resource("/games")
|
||||
class Games
|
||||
|
||||
/**
|
||||
* API routes to show all games.
|
||||
*/
|
||||
fun Route.readGamesList(gameListRepository: GameListRepository) {
|
||||
authenticate {
|
||||
// Read the last played card on the game.
|
||||
get<Games> {
|
||||
val gameList = gameListRepository.getList()
|
||||
call.respond(gameList)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import io.ktor.server.routing.Route
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
@Resource("/game/{id}")
|
||||
@Resource("/games/{id}")
|
||||
class Game(
|
||||
@Serializable(with = GameIdSerializer::class)
|
||||
val id: GameId,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package eventDemo.business.event.projection.gameList
|
||||
|
||||
import eventDemo.business.entity.GameId
|
||||
import eventDemo.business.entity.Player
|
||||
import eventDemo.business.event.projection.Projection
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class GameList(
|
||||
override val aggregateId: GameId,
|
||||
override val lastEventVersion: Int = 0,
|
||||
val status: Status = Status.OPENING,
|
||||
val players: Set<Player> = emptySet(),
|
||||
val winners: Set<Player> = emptySet(),
|
||||
) : Projection<GameId> {
|
||||
enum class Status {
|
||||
OPENING,
|
||||
IS_STARTED,
|
||||
FINISH,
|
||||
CANCELED,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package eventDemo.business.event.projection.gameList
|
||||
|
||||
import eventDemo.business.event.event.CardIsPlayedEvent
|
||||
import eventDemo.business.event.event.GameEvent
|
||||
import eventDemo.business.event.event.GameStartedEvent
|
||||
import eventDemo.business.event.event.NewPlayerEvent
|
||||
import eventDemo.business.event.event.PlayerChoseColorEvent
|
||||
import eventDemo.business.event.event.PlayerHavePassEvent
|
||||
import eventDemo.business.event.event.PlayerReadyEvent
|
||||
import eventDemo.business.event.event.PlayerWinEvent
|
||||
|
||||
fun GameList.apply(event: GameEvent): GameList =
|
||||
when (event) {
|
||||
is NewPlayerEvent -> {
|
||||
copy(
|
||||
players = players + event.player,
|
||||
status = GameList.Status.OPENING,
|
||||
)
|
||||
}
|
||||
|
||||
is GameStartedEvent -> {
|
||||
copy(
|
||||
status = GameList.Status.IS_STARTED,
|
||||
)
|
||||
}
|
||||
|
||||
is PlayerWinEvent -> {
|
||||
copy(
|
||||
winners = winners + event.player,
|
||||
status = GameList.Status.FINISH,
|
||||
)
|
||||
}
|
||||
|
||||
is CardIsPlayedEvent -> {
|
||||
this
|
||||
}
|
||||
|
||||
is PlayerChoseColorEvent -> {
|
||||
this
|
||||
}
|
||||
|
||||
is PlayerHavePassEvent -> {
|
||||
this
|
||||
}
|
||||
|
||||
is PlayerReadyEvent -> {
|
||||
this
|
||||
}
|
||||
}.copy(
|
||||
lastEventVersion = event.version,
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
package eventDemo.business.event.projection.gameList
|
||||
|
||||
interface GameListRepository {
|
||||
fun getList(): List<GameList>
|
||||
}
|
||||
@@ -2,9 +2,11 @@ package eventDemo.configuration.injection
|
||||
|
||||
import eventDemo.adapter.infrastructureLayer.event.GameEventBusInMemory
|
||||
import eventDemo.adapter.infrastructureLayer.event.GameEventStoreInMemory
|
||||
import eventDemo.adapter.infrastructureLayer.event.projection.GameListRepositoryInMemory
|
||||
import eventDemo.adapter.infrastructureLayer.event.projection.GameStateRepositoryInMemory
|
||||
import eventDemo.business.event.GameEventBus
|
||||
import eventDemo.business.event.GameEventStore
|
||||
import eventDemo.business.event.projection.gameList.GameListRepository
|
||||
import eventDemo.business.event.projection.gameState.GameStateRepository
|
||||
import eventDemo.libs.event.projection.SnapshotConfig
|
||||
import org.koin.core.module.Module
|
||||
@@ -22,4 +24,8 @@ fun Module.configureDIInfrastructure() {
|
||||
single {
|
||||
GameStateRepositoryInMemory(get(), get(), snapshotConfig = SnapshotConfig())
|
||||
} bind GameStateRepository::class
|
||||
|
||||
single {
|
||||
GameListRepositoryInMemory(get(), get(), snapshotConfig = SnapshotConfig())
|
||||
} bind GameListRepository::class
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eventDemo.configuration.route
|
||||
|
||||
import eventDemo.adapter.interfaceLayer.readGamesList
|
||||
import eventDemo.adapter.interfaceLayer.readTheGameState
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.routing.routing
|
||||
@@ -8,5 +9,6 @@ import org.koin.ktor.ext.get
|
||||
fun Application.declareHttpGameRoute() {
|
||||
routing {
|
||||
readTheGameState(get())
|
||||
readGamesList(get())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class ProjectionSnapshotRepositoryInMemory<E : Event<ID>, P : Projection<ID>, ID
|
||||
* 6. remove old one
|
||||
*/
|
||||
fun applyAndPutToCache(event: E) {
|
||||
if ((event.version % snapshotCacheConfig.modulo) == 0) {
|
||||
if ((event.version % snapshotCacheConfig.modulo) == 1) {
|
||||
getUntil(event)
|
||||
.also {
|
||||
save(it)
|
||||
@@ -51,6 +51,14 @@ class ProjectionSnapshotRepositoryInMemory<E : Event<ID>, P : Projection<ID>, ID
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the list of all [Projections][Projection]
|
||||
*/
|
||||
fun getList(): List<P> =
|
||||
projectionsSnapshot.map { (id, b) ->
|
||||
getLast(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the last version of the [Projection] from the cache.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user