diff --git a/elmslie-core/src/main/kotlin/money/vivid/elmslie/core/store/Actor.kt b/elmslie-core/src/main/kotlin/money/vivid/elmslie/core/store/Actor.kt index c59efce6..652c8708 100644 --- a/elmslie-core/src/main/kotlin/money/vivid/elmslie/core/store/Actor.kt +++ b/elmslie-core/src/main/kotlin/money/vivid/elmslie/core/store/Actor.kt @@ -3,9 +3,13 @@ package money.vivid.elmslie.core.store import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.mapNotNull +import money.vivid.elmslie.core.switcher.Switcher +import kotlin.reflect.KClass abstract class Actor { + private val switchers = mutableMapOf, Switcher>() + /** * Executes a command. This method is performed on the [Dispatchers.IO] * [kotlinx.coroutines.Dispatchers.IO] which is set by ElmslieConfig.ioDispatchers() @@ -17,4 +21,24 @@ abstract class Actor { errorMapper: (error: Throwable) -> Event? = { null }, ) = mapNotNull { eventMapper(it) } .catch { errorMapper(it)?.let { event -> emit(event) } ?: throw it } + + protected fun switchFlow( + command: Command, + delayMillis: Long = 0, + flow: () -> Flow + ): Flow { + val switcher = switchers.getOrPut(command::class) { + Switcher() + } + return switcher.switch(delayMillis) { + flow.invoke() + } + } + + protected fun Flow.switchOnEach(command: Command, delayMillis: Long = 0): Flow { + val switcher = switchers.getOrPut(command::class) { + Switcher() + } + return switcher.switch(delayMillis) { this } + } } diff --git a/samples/coroutines-loader/src/main/kotlin/money/vivid/elmslie/samples/coroutines/timer/elm/TimerActor.kt b/samples/coroutines-loader/src/main/kotlin/money/vivid/elmslie/samples/coroutines/timer/elm/TimerActor.kt index ce9c076a..87cb1efc 100644 --- a/samples/coroutines-loader/src/main/kotlin/money/vivid/elmslie/samples/coroutines/timer/elm/TimerActor.kt +++ b/samples/coroutines-loader/src/main/kotlin/money/vivid/elmslie/samples/coroutines/timer/elm/TimerActor.kt @@ -1,6 +1,7 @@ package money.vivid.elmslie.samples.coroutines.timer.elm import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import money.vivid.elmslie.core.store.Actor import money.vivid.elmslie.core.switcher.Switcher @@ -11,18 +12,24 @@ internal object TimerActor : Actor() { override fun execute(command: Command) = when (command) { - is Command.Start -> - switcher - .switch { secondsFlow() } - .mapEvents( - eventMapper = { Event.OnTimeTick }, - errorMapper = { Event.OnTimeError(it) }, - ) +// is Command.Start -> switchFlow(command) { +// secondsFlow() +// }.mapEvents( +// eventMapper = { Event.OnTimeTick }, +// errorMapper = { Event.OnTimeError(it) }, +// ) + is Command.Start -> secondsFlow() + .switchOnEach(command) + .mapEvents( + eventMapper = { Event.OnTimeTick }, + errorMapper = { Event.OnTimeError(it) }, + ) + is Command.Stop -> switcher.cancel() } @Suppress("MagicNumber") - private fun secondsFlow() = flow { + private fun secondsFlow(): Flow = flow { repeat(10) { delay(1000) emit(it)