Type-safe event bus for Kotlin. DI-resolved listeners, middleware, coroutines — lightweight and thread-safe.
implementation("com.cristianllanos:events:1.0.0")Events are data classes. Listeners are generic. The compiler catches type mismatches at build time.
Listeners are resolved from the container on each emit — dependencies auto-injected, no manual wiring.
Inline handlers, auto-unsubscribing one-shots, and catch-all listeners without creating a class.
Intercept every dispatch for logging, metrics, or tracing. Call next to continue or omit to short-circuit.
Suspending listeners and emit. Mix sync and async handlers on the same bus.
Snapshot-based dispatch, atomic once, concurrent subscribe/emit/clear from any thread.
Define events as data classes, listeners with injected dependencies, and emit.
data class UserCreated(val name: String) : Event
class SendWelcomeEmail(private val mailer: Mailer) : Listener<UserCreated> {
override fun handle(event: UserCreated) {
mailer.send("Welcome, ${event.name}!")
}
}
val container = Container()
EventServiceProvider().register(container)
val bus = container.resolve<EventBus>()
bus.subscribe<UserCreated, SendWelcomeEmail>()
bus.emit(UserCreated("Alice"))Inline handlers without creating a class. One-shots auto-unsubscribe after the first invocation.
val sub = bus.on<UserCreated> { event ->
println("New user: ${event.name}")
}
sub.cancel()
bus.once<UserCreated> { event ->
println("First user only: ${event.name}")
}
bus.onAny { event -> println("All events: $event") }Intercept event dispatch for cross-cutting concerns like timing, logging, or tracing.
bus.use { event, next ->
val start = System.nanoTime()
next(event) // call next to continue the pipeline
println("${event::class.simpleName} in ${System.nanoTime() - start}ns")
}Suspending listeners and emit — mix sync and async handlers on the same bus.
class AsyncWelcomeEmail(private val mailer: SuspendingMailer) : SuspendingListener<UserCreated> {
override suspend fun handle(event: UserCreated) {
mailer.send("Welcome, ${event.name}!")
}
}
val bus = SuspendingEventBus(container)
bus.subscribeSuspending<UserCreated, AsyncWelcomeEmail>()
bus.on<UserCreated> { event -> delay(100); println(event.name) }
coroutineScope { bus.emit(UserCreated("Alice")) }Install, define events and listeners, wire up with a DI container.
Lambda handlers, one-shot, catch-all, registration DSL, unsubscribe.
Middleware pipeline, error resilience, inspector, event hierarchy.
Suspending listeners and emit, mixed handlers, incremental migration.
Thread safety, interface segregation, once guarantees.
Complete public API: interfaces, extension functions, types, and exceptions.
Release history and notable changes.
Add the dependency, subscribe a listener, and emit. That's it.