All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.EventProcessor.kt Maven / Gradle / Ivy

package kt.mobius

import kt.mobius.functions.Consumer
import kotlin.js.JsName

/**
 * Processes events and emits effects and models as a result of that.
 *
 * @param [M] model type
 * @param [E] event type
 * @param [F] effect descriptor type
 */
class EventProcessor internal constructor(
    val store: MobiusStore,
    val effectConsumer: Consumer,
    val modelConsumer: Consumer
) {
    private object LOCK

    // concurrency note: the two below fields are only read and written in synchronized sections,
    // hence no need for further coordination.
    private val eventsReceivedBeforeInit = ArrayList()
    private var initialised = false

    fun init(): Unit = mpp.synchronized(LOCK) {
        if (initialised) {
            throw IllegalStateException("already initialised")
        }

        val first = store.init()

        dispatchModel(first.model())
        dispatchEffects(first.effects())

        initialised = true
        for (event in eventsReceivedBeforeInit) {
            update(event)
        }
    }

    fun update(event: E): Unit = mpp.synchronized(LOCK) {
        if (!initialised) {
            eventsReceivedBeforeInit.add(event)
            return
        }

        val next = store.update(event)

        next.ifHasModel(
            object : Consumer {
                override fun accept(value: M) {
                    dispatchModel(value)
                }
            })
        dispatchEffects(next.effects())
    }

    private fun dispatchModel(model: M) {
        modelConsumer.accept(model)
    }

    private fun dispatchEffects(effects: Iterable) {
        for (effect in effects) {
            effectConsumer.accept(effect)
        }
    }

    /**
     * Factory for event processors.
     *
     * @param [M] model type
     * @param [E] event type
     * @param [F] effect descriptor type
     */
    data class Factory(val store: MobiusStore) {

        @JsName("create")
        fun create(effectConsumer: Consumer, modelConsumer: Consumer): EventProcessor {
            return EventProcessor(store, effectConsumer, modelConsumer)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy