Мне нужно выполнить некоторую инициализацию моего приложения Ktor, но я хочу сделать это только после того, как Netty будет готова принимать соединения.С другой стороны, я не хочу, чтобы такая инициализация происходила, если Netty не запускалась (например, с типичным «адресом, который уже используется»).
Я реализовал простой подход (см. Ниже),но мне интересно, возможно ли сделать это менее уродливым способом ?
Сначала я сохраняю ссылку на NettyApplicationEngine:
embeddedServer = embeddedServer(Netty, port, module)
Затем я использую channels
поле из NettyApplicationEngine для определения его состояния:
private fun NettyApplicationEngine.channelsReady(): Boolean {
val channelsField = this::class.members.find { it.name == "channels" }!!
channelsField.isAccessible = true
val channels = channelsField.call(this) as List<Channel>?
return !channels.isNullOrEmpty() && channels.all { it.isActive }
}
И, наконец, я ловлю событие ApplicationStarted и вращаюсь, пока каналы не будут готовы:
environment.monitor.subscribe(ApplicationStarted) {
thread(start = true, name = "real netty postinit") {
for (i in 1..100) {
TimeUnit.MILLISECONDS.sleep(100)
if (embeddedServer.channelsReady()) break
}
if (embeddedServer.channelsReady()) {
// Initialization here
} else {
// Server didn't start
embeddedServer.stop(1, 1, TimeUnit.SECONDS)
}
}
}