- 新增 PipelineConfigCheck(@Context):退避档位/播种取值校验不再等 autostart(CLM-7、OPS-1) - OperationDayZoneCheck 扩展 cutoff-hour 0-23 校验 - reference.md 新增「启动必需配置与显式开关」:必需清单、缺值路径、显式开关与运行时故障的边界 - PipelinePropsBindingTest 补一致退避档位;补非法值/范围用例
65 lines
2.3 KiB
Kotlin
65 lines
2.3 KiB
Kotlin
package com.gzzn.omms.msgexchange
|
|
|
|
import com.gzzn.omms.msgexchange.delivery.Dispatcher
|
|
import com.gzzn.omms.msgexchange.ingress.InboxPoller
|
|
import com.gzzn.omms.msgexchange.processing.Pump
|
|
import com.gzzn.omms.msgexchange.jobs.JobRunner
|
|
import io.micronaut.context.annotation.Requires
|
|
import io.micronaut.runtime.event.annotation.EventListener
|
|
import io.micronaut.runtime.server.event.ServerStartupEvent
|
|
import jakarta.annotation.PreDestroy
|
|
import jakarta.inject.Singleton
|
|
|
|
/**
|
|
* 管道的启动与停机:服务起来后拉起 inbox 轮询、主泵、投递三条循环,每条各占一个专用平台线程;
|
|
* 停机时先让它们各自收尾,再中断线程解除 sleep 并等待退出。
|
|
*
|
|
* 只有配置 msgx.pipeline.autostart=true 时才装配,默认不开:得有真实仓储或者 msgx.stubs=true
|
|
* 才能安全自启。
|
|
*/
|
|
@Requires(property = "msgx.pipeline.autostart", value = "true")
|
|
@Singleton
|
|
class PipelineLifecycle(
|
|
private val poller: InboxPoller,
|
|
private val pump: Pump,
|
|
private val dispatcher: Dispatcher,
|
|
private val jobRunner: JobRunner,
|
|
) {
|
|
private val log = org.slf4j.LoggerFactory.getLogger(PipelineLifecycle::class.java)
|
|
private val threads = mutableListOf<Thread>()
|
|
|
|
@Volatile
|
|
private var started = false
|
|
|
|
@EventListener
|
|
fun start(event: ServerStartupEvent) {
|
|
startIfNeeded()
|
|
}
|
|
|
|
private fun startIfNeeded() {
|
|
if (started) return
|
|
// 管道参数合法性已由 PipelineConfigCheck 在启动时无条件校验(CLM-7);
|
|
// 这里只负责拉起循环线程。
|
|
started = true
|
|
threads += spawn("msgx-inbox-poller", poller::loop)
|
|
threads += spawn("msgx-pump", pump::loop)
|
|
threads += spawn("msgx-dispatcher", dispatcher::loop)
|
|
jobRunner.start()
|
|
log.info("pipeline loops started (inbox-poller, pump, dispatcher, jobs)")
|
|
}
|
|
|
|
private fun spawn(name: String, body: () -> Unit): Thread =
|
|
Thread.ofPlatform().name(name).daemon(true).start { body() }
|
|
|
|
@PreDestroy
|
|
fun stop() {
|
|
poller.stop()
|
|
pump.stop()
|
|
dispatcher.stop()
|
|
jobRunner.stop()
|
|
threads.forEach { it.interrupt() } // 打断 sleep,让循环立刻醒过来退出,而不是干等一轮间隔
|
|
threads.forEach { runCatching { it.join(3000) } }
|
|
log.info("pipeline loops stopped")
|
|
}
|
|
}
|