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() @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") } }