Skip to content

Commit

Permalink
Merge pull request #200 from fraktalio/feature/experimental-coroutine…
Browse files Browse the repository at this point in the history
…s-api

Properly propagating `ExperimentalCoroutinesApi`
  • Loading branch information
idugalic authored May 14, 2023
2 parents 184dd57 + 43c7b22 commit 9ce2782
Show file tree
Hide file tree
Showing 40 changed files with 131 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.fraktalio.fmodel.application
import arrow.core.Either
import arrow.core.raise.either
import com.fraktalio.fmodel.application.Error.CommandHandlingFailed
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.*

Expand Down Expand Up @@ -47,6 +48,7 @@ fun <C, S, E> EventSourcingAggregate<C, S, E>.handleWithEffect(command: C): Flow
*
* @author Иван Дугалић / Ivan Dugalic / @idugalic
*/
@ExperimentalCoroutinesApi
@FlowPreview
fun <C, S, E> EventSourcingOrchestratingAggregate<C, S, E>.handleWithEffect(command: C): Flow<Either<Error, E>> =
command
Expand Down Expand Up @@ -85,6 +87,7 @@ fun <C, S, E, V> EventSourcingLockingAggregate<C, S, E, V>.handleOptimisticallyW
*
* @author Иван Дугалић / Ivan Dugalic / @idugalic
*/
@ExperimentalCoroutinesApi
@FlowPreview
fun <C, S, E, V> EventSourcingLockingOrchestratingAggregate<C, S, E, V>.handleOptimisticallyWithEffect(command: C): Flow<Either<Error, Pair<E, V>>> =
command
Expand All @@ -95,24 +98,28 @@ fun <C, S, E, V> EventSourcingLockingOrchestratingAggregate<C, S, E, V>.handleOp
.catch { emit(either { raise(CommandHandlingFailed(command)) }) }


@ExperimentalCoroutinesApi
@FlowPreview
fun <C, S, E> EventSourcingAggregate<C, S, E>.handleWithEffect(commands: Flow<C>): Flow<Either<Error, E>> =
commands
.flatMapConcat { handleWithEffect(it) }
.catch { emit(either { raise(CommandHandlingFailed(it)) }) }

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, S, E> EventSourcingOrchestratingAggregate<C, S, E>.handleWithEffect(commands: Flow<C>): Flow<Either<Error, E>> =
commands
.flatMapConcat { handleWithEffect(it) }
.catch { emit(either { raise(CommandHandlingFailed(it)) }) }

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, S, E, V> EventSourcingLockingAggregate<C, S, E, V>.handleOptimisticallyWithEffect(commands: Flow<C>): Flow<Either<Error, Pair<E, V>>> =
commands
.flatMapConcat { handleOptimisticallyWithEffect(it) }
.catch { emit(either { raise(CommandHandlingFailed(it)) }) }

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, S, E, V> EventSourcingLockingOrchestratingAggregate<C, S, E, V>.handleOptimisticallyWithEffect(commands: Flow<C>): Flow<Either<Error, Pair<E, V>>> =
commands
Expand All @@ -123,6 +130,7 @@ fun <C, S, E, V> EventSourcingLockingOrchestratingAggregate<C, S, E, V>.handleOp
fun <C, E> C.publishWithEffect(aggregate: EventSourcingAggregate<C, *, E>): Flow<Either<Error, E>> =
aggregate.handleWithEffect(this)

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, E> C.publishWithEffect(aggregate: EventSourcingOrchestratingAggregate<C, *, E>): Flow<Either<Error, E>> =
aggregate.handleWithEffect(this)
Expand All @@ -131,22 +139,27 @@ fun <C, E> C.publishWithEffect(aggregate: EventSourcingOrchestratingAggregate<C,
fun <C, E, V> C.publishOptimisticallyWithEffect(aggregate: EventSourcingLockingAggregate<C, *, E, V>): Flow<Either<Error, Pair<E, V>>> =
aggregate.handleOptimisticallyWithEffect(this)

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, E, V> C.publishOptimisticallyWithEffect(aggregate: EventSourcingLockingOrchestratingAggregate<C, *, E, V>): Flow<Either<Error, Pair<E, V>>> =
aggregate.handleOptimisticallyWithEffect(this)

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, E> Flow<C>.publishWithEffect(aggregate: EventSourcingAggregate<C, *, E>): Flow<Either<Error, E>> =
aggregate.handleWithEffect(this)

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, E> Flow<C>.publishWithEffect(aggregate: EventSourcingOrchestratingAggregate<C, *, E>): Flow<Either<Error, E>> =
aggregate.handleWithEffect(this)

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, E, V> Flow<C>.publishOptimisticallyWithEffect(aggregate: EventSourcingLockingAggregate<C, *, E, V>): Flow<Either<Error, Pair<E, V>>> =
aggregate.handleOptimisticallyWithEffect(this)

@ExperimentalCoroutinesApi
@FlowPreview
fun <C, E, V> Flow<C>.publishOptimisticallyWithEffect(aggregate: EventSourcingLockingOrchestratingAggregate<C, *, E, V>): Flow<Either<Error, Pair<E, V>>> =
aggregate.handleOptimisticallyWithEffect(this)
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import arrow.core.Either
import arrow.core.raise.either
import com.fraktalio.fmodel.application.Error.ActionResultHandlingFailed
import com.fraktalio.fmodel.application.Error.ActionResultPublishingFailed
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
Expand Down Expand Up @@ -49,6 +50,7 @@ fun <AR, A> SagaManager<AR, A>.handleWithEffect(actionResult: AR): Flow<Either<E
*
* @author Иван Дугалић / Ivan Dugalic / @idugalic
*/
@ExperimentalCoroutinesApi
@FlowPreview
fun <AR, A> SagaManager<AR, A>.handleWithEffect(actionResults: Flow<AR>): Flow<Either<Error, A>> =
actionResults
Expand All @@ -75,6 +77,7 @@ fun <AR, A> AR.publishWithEffect(sagaManager: SagaManager<AR, A>): Flow<Either<E
*
* @author Иван Дугалић / Ivan Dugalic / @idugalic
*/
@ExperimentalCoroutinesApi
@FlowPreview
fun <AR, A> Flow<AR>.publishWithEffect(sagaManager: SagaManager<AR, A>): Flow<Either<Error, A>> =
sagaManager.handleWithEffect(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.fraktalio.fmodel.domain.examples.numbers.even.command.evenNumberDecid
import com.fraktalio.fmodel.domain.examples.numbers.odd.command.oddNumberDecider
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldContainExactly
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
Expand All @@ -31,7 +32,7 @@ private fun <C, S, E> IDecider<C, S, E>.given(
repository: EventRepository<C, E>,
command: () -> C
): Flow<Either<Error, E>> =
eventSourcingAggregate(
EventSourcingAggregate(
decider = this,
eventRepository = repository
).handleWithEffect(command())
Expand All @@ -41,7 +42,7 @@ private fun <C, S, E, V> IDecider<C, S, E>.given(
repository: EventLockingRepository<C, E, V>,
command: () -> C
): Flow<Either<Error, Pair<E, V>>> =
eventSourcingLockingAggregate(
EventSourcingLockingAggregate(
decider = this,
eventRepository = repository
).handleOptimisticallyWithEffect(command())
Expand All @@ -64,6 +65,7 @@ private suspend infix fun <E, V> Flow<Either<Error, Pair<E, V>>>.thenEventPairs(
/**
* Event sourced aggregate test
*/
@OptIn(ExperimentalCoroutinesApi::class)
@FlowPreview
class EventSourcedAggregateTest : FunSpec({
val evenDecider = evenNumberDecider()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import io.kotest.matchers.types.shouldBeInstanceOf
* DSL - Given
*/
private suspend fun <S, E> IView<S, E>.given(repository: ViewStateRepository<E, S>, event: () -> E): Either<Error, S> =
materializedView(
MaterializedView(
view = this,
viewStateRepository = repository
).handleWithEffect(event())
Expand All @@ -34,7 +34,7 @@ private suspend fun <S, E, V> IView<S, E>.given(
repository: ViewStateLockingRepository<E, S, V>,
event: () -> E
): Either<Error, Pair<S, V>> =
materializedLockingView(
MaterializedLockingView(
view = this,
viewStateRepository = repository
).handleOptimisticallyWithEffect(event())
Expand All @@ -51,23 +51,23 @@ private fun <S, E> IView<S, E>.whenEvent(event: E): E = event
private infix fun <S> Either<Error, S>.thenState(expected: S) {
val state = when (this) {
is Either.Right -> value
is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value ${value}")
is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value $value")
}
state shouldBe expected
}

private infix fun <S, V> Either<Error, Pair<S, V>>.thenStateAndVersion(expected: Pair<S, V>) {
val state = when (this) {
is Either.Right -> value
is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value ${value}")
is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value $value")
}
state shouldBe expected
}


private fun <S> Either<Error, S>.thenError() {
val error = when (this) {
is Either.Right -> throw AssertionError("Expected Either.Left, but found Either.Right with value ${value}")
is Either.Right -> throw AssertionError("Expected Either.Left, but found Either.Right with value $value")
is Either.Left -> value
}
error.shouldBeInstanceOf<Error>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.fraktalio.fmodel.domain.examples.numbers.odd.command.oddNumberDecider
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.types.shouldBeInstanceOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview

/**
Expand All @@ -29,7 +30,7 @@ private suspend fun <C, S, E> IDecider<C, S, E>.given(
repository: StateRepository<C, S>,
command: () -> C
): Either<Error, S> =
stateStoredAggregate(
StateStoredAggregate(
decider = this,
stateRepository = repository
).handleWithEffect(command())
Expand All @@ -39,7 +40,7 @@ private suspend fun <C, S, E, V> IDecider<C, S, E>.given(
repository: StateLockingRepository<C, S, V>,
command: () -> C
): Either<Error, Pair<S, V>> =
stateStoredLockingAggregate(
StateStoredLockingAggregate(
decider = this,
stateRepository = repository
).handleOptimisticallyWithEffect(command())
Expand All @@ -56,23 +57,23 @@ private fun <C, S, E> IDecider<C, S, E>.whenCommand(command: C): C = command
private infix fun <S> Either<Error, S>.thenState(expected: S) {
val state = when (this) {
is Either.Right -> value
is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value ${value}")
is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value $value")
}
state shouldBe expected
}

private infix fun <S, V> Either<Error, Pair<S, V>>.thenStateAndVersion(expected: Pair<S, V>) {
val state = when (this) {
is Either.Right -> value
is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value ${value}")
is Either.Left -> throw AssertionError("Expected Either.Right, but found Either.Left with value $value")
}
state shouldBe expected
}


private suspend fun <S> Either<Error, S>.thenError() {
private fun <S> Either<Error, S>.thenError() {
val error = when (this) {
is Either.Right -> throw AssertionError("Expected Either.Left, but found Either.Right with value ${value}")
is Either.Right -> throw AssertionError("Expected Either.Left, but found Either.Right with value $value")
is Either.Left -> value
}
error.shouldBeInstanceOf<Error>()
Expand All @@ -81,6 +82,7 @@ private suspend fun <S> Either<Error, S>.thenError() {
/**
* State-stored aggregate test
*/
@OptIn(ExperimentalCoroutinesApi::class)
@FlowPreview
class StateStoredAggregateTest : FunSpec({
val evenDecider = evenNumberDecider()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package com.fraktalio.fmodel.application.examples.numbers

import com.fraktalio.fmodel.application.EventRepository
import com.fraktalio.fmodel.application.eventSourcingOrchestratingAggregate
import com.fraktalio.fmodel.application.EventSourcingOrchestratingAggregate
import com.fraktalio.fmodel.domain.Decider
import com.fraktalio.fmodel.domain.Saga
import com.fraktalio.fmodel.domain.combine
Expand All @@ -28,6 +28,7 @@ import com.fraktalio.fmodel.domain.examples.numbers.api.NumberCommand.OddNumberC
import com.fraktalio.fmodel.domain.examples.numbers.api.NumberEvent
import com.fraktalio.fmodel.domain.examples.numbers.api.NumberEvent.OddNumberEvent
import com.fraktalio.fmodel.domain.examples.numbers.api.OddNumberState
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview


Expand All @@ -41,7 +42,7 @@ import kotlinx.coroutines.FlowPreview
* @param repository the event-sourcing repository for all (even and odd) numbers
* @return the event-sourcing aggregate instance for all (even and odd) numbers
*/
@OptIn(FlowPreview::class)
@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
fun numberAggregate(
evenNumberDecider: Decider<EvenNumberCommand?, EvenNumberState, NumberEvent.EvenNumberEvent?>,
oddNumberDecider: Decider<OddNumberCommand?, OddNumberState, OddNumberEvent?>,
Expand All @@ -50,7 +51,7 @@ fun numberAggregate(
repository: EventRepository<NumberCommand?, NumberEvent?>
) =

eventSourcingOrchestratingAggregate(
EventSourcingOrchestratingAggregate(
decider = evenNumberDecider.combine(oddNumberDecider),
eventRepository = repository,
saga = evenNumberSaga.combine(oddNumberSaga)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package com.fraktalio.fmodel.application.examples.numbers

import com.fraktalio.fmodel.application.MaterializedView
import com.fraktalio.fmodel.application.ViewStateRepository
import com.fraktalio.fmodel.application.materializedView
import com.fraktalio.fmodel.domain.View
import com.fraktalio.fmodel.domain.combine
import com.fraktalio.fmodel.domain.examples.numbers.api.EvenNumberState
Expand All @@ -43,7 +42,7 @@ fun numberMaterializedView(
evenView: View<EvenNumberState?, EvenNumberEvent?>,
repository: ViewStateRepository<NumberEvent?, Pair<EvenNumberState?, OddNumberState?>>
): MaterializedView<Pair<EvenNumberState?, OddNumberState?>, NumberEvent?> =
materializedView(
MaterializedView(
view = evenView.combine(oddView),
viewStateRepository = repository
)
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package com.fraktalio.fmodel.application.examples.numbers

import com.fraktalio.fmodel.application.StateRepository
import com.fraktalio.fmodel.application.stateStoredOrchestratingAggregate
import com.fraktalio.fmodel.application.StateStoredOrchestratingAggregate
import com.fraktalio.fmodel.domain.Decider
import com.fraktalio.fmodel.domain.Saga
import com.fraktalio.fmodel.domain.combine
Expand All @@ -28,6 +28,7 @@ import com.fraktalio.fmodel.domain.examples.numbers.api.NumberCommand.OddNumberC
import com.fraktalio.fmodel.domain.examples.numbers.api.NumberEvent
import com.fraktalio.fmodel.domain.examples.numbers.api.NumberEvent.OddNumberEvent
import com.fraktalio.fmodel.domain.examples.numbers.api.OddNumberState
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview


Expand All @@ -41,15 +42,15 @@ import kotlinx.coroutines.FlowPreview
* @param repository the state-stored repository for all (even and odd) numbers
* @return the state-stored aggregate instance for all (even and odd) numbers
*/
@OptIn(FlowPreview::class)
@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
fun numberStateStoredAggregate(
evenNumberDecider: Decider<EvenNumberCommand?, EvenNumberState, NumberEvent.EvenNumberEvent?>,
oddNumberDecider: Decider<OddNumberCommand?, OddNumberState, OddNumberEvent?>,
evenNumberSaga: Saga<NumberEvent.EvenNumberEvent?, OddNumberCommand>,
oddNumberSaga: Saga<OddNumberEvent?, EvenNumberCommand>,
repository: StateRepository<NumberCommand?, Pair<EvenNumberState, OddNumberState>>
) =
stateStoredOrchestratingAggregate(
StateStoredOrchestratingAggregate(
decider = evenNumberDecider.combine(oddNumberDecider),
stateRepository = repository,
saga = evenNumberSaga.combine(oddNumberSaga)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package com.fraktalio.fmodel.application.examples.numbers.even.command

import com.fraktalio.fmodel.application.EventRepository
import com.fraktalio.fmodel.application.EventSourcingAggregate
import com.fraktalio.fmodel.application.eventSourcingAggregate
import com.fraktalio.fmodel.domain.Decider
import com.fraktalio.fmodel.domain.examples.numbers.api.EvenNumberState
import com.fraktalio.fmodel.domain.examples.numbers.api.NumberCommand.EvenNumberCommand
Expand All @@ -37,7 +36,7 @@ fun evenNumberAggregate(
repository: EventRepository<EvenNumberCommand?, NumberEvent.EvenNumberEvent?>
): EventSourcingAggregate<EvenNumberCommand?, EvenNumberState, NumberEvent.EvenNumberEvent?> =

eventSourcingAggregate(
EventSourcingAggregate(
decider = decider,
eventRepository = repository
)
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package com.fraktalio.fmodel.application.examples.numbers.even.command

import com.fraktalio.fmodel.application.StateRepository
import com.fraktalio.fmodel.application.StateStoredAggregate
import com.fraktalio.fmodel.application.stateStoredAggregate
import com.fraktalio.fmodel.domain.Decider
import com.fraktalio.fmodel.domain.examples.numbers.api.EvenNumberState
import com.fraktalio.fmodel.domain.examples.numbers.api.NumberCommand.EvenNumberCommand
Expand All @@ -37,7 +36,7 @@ fun evenNumberStateStoredAggregate(
repository: StateRepository<EvenNumberCommand?, EvenNumberState>
): StateStoredAggregate<EvenNumberCommand?, EvenNumberState, NumberEvent.EvenNumberEvent?> =

stateStoredAggregate(
StateStoredAggregate(
decider = decider,
stateRepository = repository
)
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package com.fraktalio.fmodel.application.examples.numbers.even.query

import com.fraktalio.fmodel.application.MaterializedView
import com.fraktalio.fmodel.application.ViewStateRepository
import com.fraktalio.fmodel.application.materializedView
import com.fraktalio.fmodel.domain.View
import com.fraktalio.fmodel.domain.examples.numbers.api.EvenNumberState
import com.fraktalio.fmodel.domain.examples.numbers.api.NumberEvent.EvenNumberEvent
Expand All @@ -33,7 +32,7 @@ import com.fraktalio.fmodel.domain.examples.numbers.api.NumberEvent.EvenNumberEv
fun evenNumberMaterializedView(
view: View<EvenNumberState?, EvenNumberEvent?>,
repository: ViewStateRepository<EvenNumberEvent?, EvenNumberState?>
): MaterializedView<EvenNumberState?, EvenNumberEvent?> = materializedView(
): MaterializedView<EvenNumberState?, EvenNumberEvent?> = MaterializedView(
view = view,
viewStateRepository = repository
)
Loading

0 comments on commit 9ce2782

Please sign in to comment.