Open
Description
Context receivers enable context-dependent declarations in Kotlin.
It enables composing contexts without using inheritance, which can simplify the application
layer of the systems / orchestrate the logic's execution.
It will eliminate the need of application interfaces, for example interface EventSourcingAggregate<C, S, E> : IDecider<C, S, E>, EventRepository<C, E>
or interface StateStoredAggregate<C, S, E> : IDecider<C, S, E>, StateRepository<C, S>
/**
* Event-sourced algorithm
* Computes new Events based on the previous Events and the Command.
*/
context (Decider<C, S, E>, C)
private fun <C, S, E> Flow<E>.computeNewEvents(): Flow<E> = flow {
val currentState = fold(initialState) { s, e -> evolve(s, e) }
val resultingEvents = decide(this@C, currentState)
emitAll(resultingEvents)
}
/**
* State-stored algorithm
* Computes new State based on the previous State and the Command.
*/
context (Decider<C, S, E>, C)
private suspend fun <C, S, E> S?.computeNewState(): S {
val currentState = this ?: initialState
val events = decide(this@C, currentState)
return events.fold(currentState) { s, e -> evolve(s, e) }
}
/**
* Publish command - Event-sourced decider
*/
context (Decider<C, S, E>, EventRepository<C, E>)
fun <C, S, E> C.publish(): Flow<E> = fetchEvents().computeNewEvents().save()
/**
* Publish command - State-stored decider
*/
context (Decider<C, S, E>, StateRepository<C, S>)
suspend fun <C, S, E> C.publish(): S = fetchState().computeNewState().save()
https://gist.github.com/idugalic/232bc21490f4a8976bc31e0acf548831
A plan is to alternatively implement context-dependent declarations by keeping current interfaces as a valid option: EventSourcingAggregate
, StateStoredAggregate
, ...
Metadata
Assignees
Labels
No labels
Activity