Handling application-level events
On the server-side, in addition to handling requests, Ktor exposes a mechanism to produce and consume global events.
For example, when the application is starting, has started, or has stopped, an event is generated and raised.You can subscribe to or unsubscribe from these events and trigger code execution.The monitor: ApplicationEvents instance, associated with the application environment, acts as the event dispatcher.
The ApplicationEvents dispatches typed EventDefinition<T> along with an object T.
You can get the monitor along with the application instance by executing application.environment.monitor.
ApplicationEvents API
The simplified API for the monitor: ApplicationEvents looks like this:
1. class ApplicationEvents {
2. fun <T> subscribe(definition: EventDefinition<T>, handler: EventHandler<T>): DisposableHandle
3. fun <T> unsubscribe(definition: EventDefinition<T>, handler: EventHandler<T>)
4. fun <T> raise(definition: EventDefinition<T>, value: T)
5. }
7. class EventDefinition<T>
9. typealias EventHandler<T> = (T) -> Unit
11. interface DisposableHandle {
12. fun dispose()
13. }
Predefined EventDefinitions
Ktor provides some predefined events that are dispatched by the engine:
1. val ApplicationStarting: EventDefinition<Application>
2. val ApplicationStarted: EventDefinition<Application>
3. val ApplicationStopPreparing: EventDefinition<ApplicationEnvironment>
4. val ApplicationStopping: EventDefinition<Application>
5. val ApplicationStopped: EventDefinition<Application>
Subscribing to events and raising them
You can subscribe to events by calling the subscribe method from the monitor.The subscribe method returns a DisposableHandle that you can call to cancel the subscription.Additionally, you can call the unsubscribe method with the same method handle to cancel the subscription.
Using the disposable:
1. val disposable = application.environment.monitor.subscribe(ApplicationStarting) { application: Application ->
2. // Handle the event using the application as subject
3. }
4. disposable.dispose() // Cancels the subscription
Using a lambda stored in a property:
1. val starting: (Application) -> Unit = { log("Application starting: $it") }
3. application.environment.monitor.subscribe(ApplicationStarting, starting) // subscribe
4. application.environment.monitor.unsubscribe(ApplicationStarting, starting) // unsubscribe
Using a method reference:
1. fun starting(application: Application) { log("Application starting: $it") }
3. application.environment.monitor.subscribe(ApplicationStarting, ::starting) // subscribe
4. application.environment.monitor.unsubscribe(ApplicationStarting, ::starting) // unsubscribe
If you want to create custom events and dispatch or raise them:
1. class MySubject
2. val MyEventDefinition = EventDefinition<MySubject>()
3. monitor.raise(MyEventDefinition, MySubject())
Examples
You can check the CallLogging feature source code that includes code subscribing to events from the application.
