Files
msgexchange-v2/src/main/kotlin/com/gzzn/omms/msgexchange/jobs/JobRunner.kt
T

77 lines
2.6 KiB
Kotlin
Raw Normal View History

package com.gzzn.omms.msgexchange.jobs
import com.gzzn.omms.msgexchange.config.HistoryProps
import com.gzzn.omms.msgexchange.config.PipelineProps
import com.gzzn.omms.msgexchange.processing.BackfillService
import jakarta.inject.Singleton
import java.time.Duration
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId
/**
* 维护作业调度(docs/design.md §6.1/§6.2):单 daemon 线程,独立于主泵——
* 作业不参与消息 FIFO,也不使到期消息饥饿(PUMP_JOB 队列机制已随审计口径移除)。
* 触发:回填补写扫描 30s 固定间隔;历史归档/留痕清理每日机场时区 03:30 后首个 tick。
* 回填意图由处理器在终态事务内登记(message-lifecycle §4),本线程只负责到期重试。
*/
@Singleton
class JobRunner(
private val backfill: BackfillService,
private val historySweep: HistorySweepJob,
@Suppress("unused") private val pipelineProps: PipelineProps,
@Suppress("unused") private val historyProps: HistoryProps,
) {
private val log = org.slf4j.LoggerFactory.getLogger(JobRunner::class.java)
private val zone: ZoneId = ZoneId.of("Asia/Shanghai")
@Volatile
private var running = true
@Volatile
private var lastHistoryDay: LocalDate? = null
private var thread: Thread? = null
fun start() {
if (thread != null) return
running = true
thread = Thread.ofPlatform().name("msgx-jobs").daemon(true).start { loop() }
log.info("job runner started (backfill 30s, history daily 03:30 {})", zone)
}
fun stop() {
running = false
thread?.interrupt()
thread = null
}
internal fun loop() {
while (running) {
try {
backfill.sweep()
maybeHistorySweep()
} catch (e: InterruptedException) {
Thread.currentThread().interrupt()
return
} catch (e: Exception) {
log.warn("job tick failed: {}", e.message ?: e.javaClass.simpleName)
}
if (running) runCatching { Thread.sleep(Duration.ofSeconds(30).toMillis()) }
}
}
private fun maybeHistorySweep() {
val today = LocalDate.now(zone)
if (lastHistoryDay == today) return
val now = java.time.LocalTime.now(zone)
if ((now.hour == 3 && now.minute >= 30) || now.hour > 3) {
val outcome = historySweep.run()
lastHistoryDay = today
if (outcome.selected > 0 || outcome.snapLogPurged > 0) {
log.info("history sweep: {}", outcome)
}
}
}
}