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

commonMain.dk.cachet.carp.common.application.services.ApplicationServiceEventBus.kt Maven / Gradle / Ivy

Go to download

Helper classes and base types relied upon by all subsystems. This library does not contain any domain logic.

The newest version!
package dk.cachet.carp.common.application.services

import kotlin.reflect.KClass


/**
 * An event bus which can be used by an [ApplicationService] to publish events associated with its service
 * and subscribe to any other events.
 */
class ApplicationServiceEventBus<
    TService : ApplicationService,
    TEvent : IntegrationEvent
>( private val serviceKlass: KClass, private val eventBus: EventBus )
{
    /**
     * Publish the specified [event].
     */
    suspend fun publish( event: TEvent ) = eventBus.publish( serviceKlass, event )

    /**
     * Subscribe to a set of events, registered by calling `event`.
     * This can only be called once.
     *
     * @throws IllegalStateException when subscribe has already been called.
     */
    fun subscribe( registerHandlers: EventSubscriptionBuilder.() -> Unit )
    {
        val builder = EventSubscriptionBuilder( serviceKlass, eventBus )
        builder.registerHandlers()
        eventBus.activateHandlers( serviceKlass )
    }
}


@DslMarker
annotation class EventSubscriptionDsl

// TODO: Apply the DSL marker to `event` to disallow calling `event` from inside `event`.
//  For that to work `event` should be a builder itself to which the marker can be applied.
//  That is currently impossible since we cannot extend from `suspend (TEvent) -> Unit`:
//  https://youtrack.jetbrains.com/issue/KT-18707
@EventSubscriptionDsl
class EventSubscriptionBuilder(
    @PublishedApi
    internal val subscriber: Any,
    @PublishedApi
    internal val eventBus: EventBus
)
{
    /**
     * Register a [handler] for events of type [TEvent] on this [ApplicationServiceEventBus].
     */
    inline fun <
        reified TService : ApplicationService,
        reified TEvent : IntegrationEvent
    > event(
        noinline handler: suspend (TEvent) -> Unit
    ) = eventBus.registerHandler( TService::class, TEvent::class, subscriber, handler )
}


/**
 * Create an adapter for this [EventBus] which can only publish events associated with [serviceKlass].
 */
fun <
    TService : ApplicationService,
    TEvent : IntegrationEvent
> EventBus.createApplicationServiceAdapter(
    serviceKlass: KClass
): ApplicationServiceEventBus = ApplicationServiceEventBus( serviceKlass, this )




© 2015 - 2024 Weber Informatics LLC | Privacy Policy