diff --git a/CHANGELOG.md b/CHANGELOG.md index fc6efed64f..b1f92d83d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 4.2.4 +* `BehaviourBuilderWithFSM`: + * Fixes in `DefaultBehaviourContextWithFSM` + ## 4.2.3 * `Versions`: diff --git a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSM.kt b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSM.kt index a96676a42f..fc9ac35f7b 100644 --- a/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSM.kt +++ b/tgbotapi.behaviour_builder.fsm/src/commonMain/kotlin/dev/inmo/tgbotapi/extensions/behaviour_builder/BehaviourContextWithFSM.kt @@ -10,6 +10,8 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar.T import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.* +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import kotlin.reflect.KClass /** @@ -133,6 +135,9 @@ class DefaultBehaviourContextWithFSM( private val additionalHandlers = mutableListOf>() private var actualHandlersList = additionalHandlers + handlers + protected val statesJobs = mutableMapOf() + protected val statesJobsMutex = Mutex() + override suspend fun launchStateHandling(state: T, handlers: List>): T? { return launchStateHandling(state, handlers, onStateHandlingErrorHandler) } @@ -165,16 +170,27 @@ class DefaultBehaviourContextWithFSM( } } statesManager.onStartChain.subscribeSafelyWithoutExceptions(this) { - launch { statePerformer(it) } + statesJobsMutex.withLock { + runCatchingSafely { statesJobs.remove(it) ?.cancel() } + + statesJobs[it] = launch { statePerformer(it) } + } + } + statesManager.onEndChain.subscribeSafelyWithoutExceptions(this) { + statesJobsMutex.withLock { + runCatchingSafely { statesJobs.remove(it) ?.cancel() } + } + updatesFlows.remove(it.context) } statesManager.onChainStateUpdated.subscribeSafelyWithoutExceptions(this) { (old, new) -> + statesJobsMutex.withLock { + runCatchingSafely { statesJobs.remove(old) ?.cancel() } + runCatchingSafely { statesJobs.remove(new) ?.cancel() } + statesJobs[new] = launch { statePerformer(new) } + } if (old.context != new.context) { updatesFlows.remove(old.context) } - launch { statePerformer(new) } - } - statesManager.onEndChain.subscribeSafelyWithoutExceptions(this) { - updatesFlows.remove(it.context) } statesManager.getActiveStates().forEach {