Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kevincianfarini/cardiologist
Build job schedules with kotlinx-datetime and kotlinx-coroutines
https://github.com/kevincianfarini/cardiologist
cron cronjob kotlin kotlin-coroutines kotlin-datetime kotlin-multiplatform kotlin-multiplatform-library kotlinx-coroutines kotlinx-datetime
Last synced: 2 days ago
JSON representation
Build job schedules with kotlinx-datetime and kotlinx-coroutines
- Host: GitHub
- URL: https://github.com/kevincianfarini/cardiologist
- Owner: kevincianfarini
- License: apache-2.0
- Created: 2023-10-04T23:40:23.000Z (over 1 year ago)
- Default Branch: trunk
- Last Pushed: 2025-02-02T17:39:30.000Z (8 days ago)
- Last Synced: 2025-02-02T18:28:49.670Z (8 days ago)
- Topics: cron, cronjob, kotlin, kotlin-coroutines, kotlin-datetime, kotlin-multiplatform, kotlin-multiplatform-library, kotlinx-coroutines, kotlinx-datetime
- Language: Kotlin
- Homepage: https://kevincianfarini.github.io/cardiologist/docs/0.x/
- Size: 629 KB
- Stars: 164
- Watchers: 6
- Forks: 5
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
- awesome-list - kevincianfarini/cardiologist - Build job schedules with kotlinx-datetime and kotlinx-coroutines (Kotlin)
README
# Cardiologist
Build job schedules with [kotlinx-datetime](https://github.com/Kotlin/kotlinx-datetime) and [kotlinx-coroutines](https://github.com/Kotlin/kotlinx.coroutines).
```kt
val tz = TimeZone.of("America/New_York")
Clock.System.schedulePulse(atSecond = 0).beat { scheduled, occurred ->
println("A pulse was scheduled in $tz for ${scheduled.toLocalDateTime(tz)} and occurred at ${occurred.toLocalDateTime(tz)}.")
}
``````
A pulse was scheduled in America/New_York for 2025-01-11T08:41 and occurred at 2025-01-11T08:41:00.005227606
A pulse was scheduled in America/New_York for 2025-01-11T08:42 and occurred at 2025-01-11T08:42:00.001463582
A pulse was scheduled in America/New_York for 2025-01-11T08:43 and occurred at 2025-01-11T08:43:00.001028731
A pulse was scheduled in America/New_York for 2025-01-11T08:44 and occurred at 2025-01-11T08:44:00.001037604
A pulse was scheduled in America/New_York for 2025-01-11T08:45 and occurred at 2025-01-11T08:45:00.001025281
A pulse was scheduled in America/New_York for 2025-01-11T08:46 and occurred at 2025-01-11T08:46:00.001062597
A pulse was scheduled in America/New_York for 2025-01-11T08:47 and occurred at 2025-01-11T08:47:00.000846953
```## Download
```toml
[versions]
cardiologist = "0.3.1"[libraries]
cardiologist = { module = "io.github.kevincianfarini.cardiologist:cardiologist", version.ref = "cardiologist" }```
## Introduction
Cardiologist integrates with kotlinx-datetime to provide you scheduling based on `Instant`, `LocalDateTime`,
and `LocalTime`, and integrates with kotlinx-coroutines to provide a suspending API to trigger pending jobs.Simple suspending functions are available to delay until a given moment in time.
```kt
Clock.System.delayUntil(instant = Instant.DISTANT_FUTURE)
Clock.System.delayUntil(dateTime = LocalDateTime.MAX, timeZone = TimeZone.UTC)
```...or suspending for a given period of time.
```kt
Clock.System.delayFor(period = DateTimePeriod(months = 1, days = 2), timeZone = TimeZone.UTC)
```...or suspending until the next time a `LocalTime` occurs in a certain time zone.
```kt
val midnight = LocalTime(hour = 0, minute = 0)
Clock.System.delayUntilNext(time = midnight, timeZone = TimeZone.UTC)
```Repeating intervals are provided as a `Pulse`, a type which holds a reccurence cadence.
```kt
val hourlyPulse: Pulse = Clock.System.intervalPulse(interval = 1.hours)
val dailyPulse: Pulse = Clock.System.intervalPulse(
period = DateTimePeriod(days = 1),
timeZone = TimeZone.UTC,
)
```Pulse schedules can be built with a cron like API.
```kt
// Schedules a pulse to occur on the 5th of every month at 12:30 in UTC.
val scheduledPulse = Clock.System.schedulePulse(
timeZone = TimeZone.UTC,
atSecond = 0,
atMinute = 30,
atHour = 12,
onDayOfMonth = 5,
)
```...and can be invoked by calling `Pulse.beat`.
```kt
scheduledPulse.beat { instant -> println("$instant") }
```Beating a pulse is a backpressure sensitive operation. If your job has not completed when the next
pulse is scheduled to occur, it will by default be cancelled. Cardiologist provides another mode
to beat a pulse which allow jobs to run concurrently.```kt
import io.github.kevincianfarini.cardiologist.RecurringJobMode.*// Cancels previous job when next job is scheduled to occur.
hourlyPulse.beat(mode = CancellingSequential) { instant -> longRunningOperation(instant) }
// Allows jobs to run concurrently if previous job is still active.
hourlyPulse.beat(mode = Concurrent) { instant -> longRunningOperation(instant) }
```## Cardiologist is not a replacement for crontab(5) or Android WorkManager.
Cardiologist is an _in process_ job scheduling library. It is meant to run concurrently to the rest of
your process, not as a separate process. Use cases include job scheduling within a long-lived process like
a server or a daemon.```kt
// With ktor, for example.
fun main() = runBlocking { // this: CoroutineScope
this.embeddedServer(Netty, port = 8080) { /* omitted */ }.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 jobs and Android's WorkManager leverage standalone processes and will launch your program as a separate processes.
This is outside the scope of Cadiologist's goals.