心脏病专家
使用 kotlinx-datetime 和 kotlinx-coroutines 构建作业调度。
val tz = TimeZone.of("America/New_York")
Clock.System.schedulePulse(atSecond = 0).beat { instant ->
println("$tz 的时间是 ${instant.toLocalDateTime(tz)}。")
}
America/New_York 的时间是 2023-10-07T19:49:00。
America/New_York 的时间是 2023-10-07T19:50:00。
America/New_York 的时间是 2023-10-07T19:51:00。
America/New_York 的时间是 2023-10-07T19:52:00。
America/New_York 的时间是 2023-10-07T19:53:00。
简介
心脏病专家与 kotlinx-datetime 集成,提供基于 Instant
、LocalDateTime
和 LocalTime
的调度功能,并与 kotlinx-coroutines 集成,提供一个挂起 API 来触发待处理的作业。
提供简单的挂起函数以延迟到指定的时间点。
Clock.System.delayUntil(instant = Instant.DISTANT_FUTURE)
Clock.System.delayUntil(dateTime = LocalDateTime.MAX, timeZone = TimeZone.UTC)
...或延迟指定的时间段。
Clock.System.delayFor(period = DateTimePeriod(months = 1, days = 2), timeZone = TimeZone.UTC)
...或延迟到某个时区的下一个 LocalTime
出现。
val midnight = LocalTime(hour = 0, minute = 0)
Clock.System.delayUntilNext(time = midnight, timeZone = TimeZone.UTC)
重复的时间间隔以 Pulse
的形式提供,这是一个保存重复周期的类型。
val hourlyPulse: Pulse = Clock.System.intervalPulse(interval = 1.hours)
val dailyPulse: Pulse = Clock.System.intervalPulse(
period = DateTimePeriod(days = 1),
timeZone = TimeZone.UTC,
)
可以使用类似 cron 的 API 构建脉冲调度。
// 安排每月 5 日 UTC 时间 12:30 发生脉冲
val scheduledPulse = Clock.System.schedulePulse(
timeZone = TimeZone.UTC,
atSecond = 0,
atMinute = 30,
atHour = 12,
onDayOfMonth = 5,
)
...并可以通过调用 Pulse.beat
来执行。
scheduledPulse.beat { instant -> println("$instant") }
脉冲的执行对背压敏感。默认情况下,如果你的作业在下一个脉冲计划发生时尚未完成,它将被取消。心脏病专家提供了两种其他模式来执行脉冲,允许作业并发运行或应用背压。
import io.github.kevincianfarini.cardiologist.RecurringJobMode.*
// 当下一个作业计划发生时取消前一个作业
hourlyPulse.beat(mode = CancellingSequential) { instant -> longRunningOperation(instant) }
// 如果前一个作业仍在活动,允许作业并发运行
hourlyPulse.beat(mode = Concurrent) { instant -> longRunningOperation(instant) }
// 在前一个作业完成之前不会再次发出,应用背压
hourlyPulse.beat(mode = DelayBetweenSequential) { instant -> longRunningOperation(instant) }
心脏病专家不是 crontab(5) 或 Android WorkManager 的替代品
心脏病专家是一个进程内作业调度库。它旨在与你的进程的其余部分并发运行,而不是作为一个单独的进程。用例包括在长期运行的进程(如服务器或守护进程)中进行作业调度。
// 例如,与 ktor 一起使用
fun main() = runBlocking { // this: CoroutineScope
this.embeddedServer(Netty, port = 8080) { /* 省略 */ }.start(wait = false)
launch { recurringJob() }
}
private suspend fun recurringJob() {
Clock.System.schedulePulse(
onDayOfMonth = 1,
atHour = 0,
atMinute = 0,
atSecond = 0
).beat { instant -> someWork(instant) }
}
Cron 作业和 Android 的 WorkManager 利用独立进程,并将你的程序作为单独的进程启动。这超出了心脏病专家的目标范围。