4 of 5
Coroutines
The events-coroutines module adds suspending listeners, suspend emit, and mixed sync/async handlers.
Suspending listeners
Implement SuspendingListener<T> when your handler needs to perform suspend operations like database writes, HTTP requests, or channel sends:
class AsyncWelcomeEmail(private val mailer: SuspendingMailer) : SuspendingListener<UserCreated> {
override suspend fun handle(event: UserCreated) {
mailer.send("Welcome, ${event.name}!")
}
}Register suspending listeners with subscribeSuspending:
val bus = SuspendingEventBus(container)
bus.subscribeSuspending<UserCreated, AsyncWelcomeEmail>()Suspending emit
SuspendingEventBus.emit() is a suspend function that awaits all handlers before returning. Call it from any coroutine scope:
coroutineScope {
bus.emit(UserCreated("Alice"))
// all listeners (sync and async) have completed here
}Mixed handlers
A SuspendingEventBus accepts both Listener and SuspendingListener registrations on the same bus. Lambda handlers registered with on are suspending by default:
// Plain listener (sync)
bus.subscribe<UserCreated, AuditLogListener>()
// Suspending listener (async)
bus.subscribeSuspending<UserCreated, AsyncWelcomeEmail>()
// Lambda — suspending by default on SuspendingEventBus
bus.on<UserCreated> { event ->
delay(100)
println(event.name)
}All handlers run in sequence during emit, regardless of whether they are sync or async.
Suspend onError
In the coroutines module, onError is a suspend function, so you can perform async work like writing to a database or sending to a channel:
val bus = SuspendingEventBus(container, onError = { e ->
errorChannel.send(e)
})Migration
You can migrate from events-core to events-coroutinesincrementally:
- Add the
events-coroutinesdependency (it includesevents-coretransitively). - Replace
EventBuswithSuspendingEventBusandEventServiceProviderwithSuspendingEventServiceProvider. - Existing
Listenerimplementations work as-is — no changes needed. - Convert listeners to
SuspendingListenerone at a time as needed.
The coroutines module mirrors the core API one-to-one:
// Core → Coroutines
// Listener<T> → SuspendingListener<T>
// Emitter → SuspendingEmitter
// Subscriber → SuspendingSubscriber
// EventBus → SuspendingEventBus
// EventServiceProvider → SuspendingEventServiceProviderdependencies {
implementation("com.cristianllanos:events-coroutines:1.0.0")
}Next steps
Learn about thread safety, interface segregation, and once guarantees.