KtScheduler is a lightweight task/job scheduling library for Kotlin, powered by Kotlin coroutines! The design of this library is inspired by the APScheduler library for Python, while keeping things simple and easy to use.
- Lightweight with no external dependencies other than
kotlinx:kotlinx-coroutines-core
from the Kotlin standard library. - Designed to respect time zones, allowing you to set the time zone yourself or use the system's time zone by default.
- Provides four different types of triggers to execute jobs daily, at certain intervals, once at a given time, or with a cron-like schedule.
- Can run multiple instances of a job concurrently while giving you the option to run only one instance if the job is already executing.
- Can be easily extended to suit your specific use case by allowing you to write custom triggers and job stores.
- Easy to use and straightforward API with full KDoc/Javadoc documentation coverage.
- 100% unit test coverage to ensure reliability across different scenarios.
Add the Jitpack repository in your build configuration:
repositories {
...
maven("https://jitpack.io")
}
Add the dependency:
dependencies {
implementation("com.github.Pool-Of-Tears:KtScheduler:version")
}
Note
Full documentation for all classes and functions in KDoc format can be found here.
Here's a quick start:
val timeZone = ZoneId.of("Asia/Kolkata")
val scheduler = KtScheduler(timeZone = timeZone)
// Create a job like this
val job = Job(
jobId = "OneTimeJob", // Must be unique for each job
trigger = OneTimeTrigger(ZonedDateTime.now(timeZone).plusSeconds(5)),
// Next runtime of the job; when creating the job for the first time,
// it will be used as the initial runtime (Optional).
nextRunTime = ZonedDateTime.now(timeZone).plusSeconds(5),
// Coroutine dispatcher in which the job should be executed.
dispatcher = Dispatchers.Default,
// Callback function that will be executed when the job is triggered.
callback = { println("OneTime Job executed at ${ZonedDateTime.now(timeZone)}") }
)
// Add it to the scheduler
scheduler.addJob(job)
// or like this! (shortcut / convinience method)
// This will create a job with a unique ID and add it to the scheduler
// See the documentation for more details on other such convinience methods.
scheduler.runRepeating(intervalSeconds = 10) {
println("Meow >~<") // every 10 seconds
}
// Finally, start the scheduler
scheduler.start()
// If you're running this as a standalone program, you need to block the current thread
// to prevent the program from exiting, since scheduler.start() is a non-blocking call.
scheduler.idle()
Triggers determine when and at what frequency a particular job should be executed. KtScheduler provides four types of triggers:
CronTrigger
- A trigger that determines the next run time based on the specified days of the week and time.
// Days when the job should fire
val daysOfWeek = setOf(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY)
val time = LocalTime.of(10, 0) // 10:00 AM (Time of the day)
val trigger = CronTrigger(daysOfWeek, time)
DailyTrigger
- A trigger that fires at a specific time every day.
// Run daily at 10:00 AM
val dailyTime = LocalTime.of(10, 0)
val trigger = DailyTrigger(dailyTime)
IntervalTrigger
- A trigger that fires at a specified interval.
val interval = 60L // Every 60 seconds
val trigger = IntervalTrigger(interval)
OneTimeTrigger
- A trigger that fires once at a specified time.
// Run after 5 seconds
val trigger = OneTimeTrigger(ZonedDateTime.now().plusSeconds(5))
You can easily create your own custom trigger by implementing the Trigger
interface.
Here's an example to create a WeekendTrigger
, a trigger that should fire on weekends at a specified time.
import dev.starry.ktscheduler.triggers.Trigger
class WeekendTrigger(private val time: LocalTime) : Trigger {
private val weekendDays = setOf(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)
override fun getNextRunTime(currentTime: ZonedDateTime, timeZone: ZoneId): ZonedDateTime {
var nextRunTime = currentTime.withZoneSameInstant(timeZone).with(time).withNano(0)
while (!weekendDays.contains(nextRunTime.dayOfWeek) ||
nextRunTime.isBefore(currentTime) ||
nextRunTime.isEqual(currentTime)
) {
nextRunTime = nextRunTime.plusDays(1)
}
return nextRunTime
}
}
You can listen for job events such as completion or failure due to errors by attaching a JobEventListener
to
the KtScheduler
. Here's an example:
import dev.starry.ktscheduler.event.JobEvent
import dev.starry.ktscheduler.event.JobEventListener
scheduler.addEventListener(object : JobEventListener {
override fun onJobComplete(event: JobEvent) {
println("Job ${event.jobId} completed successfully at ${event.timestamp}")
}
override fun onJobError(event: JobEvent) {
println("Job ${event.jobId} failed with exception ${event.exception} at ${event.timestamp}")
}
})
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change, or feel free to tackle any of the open issues present at the moment. If you're doing the latter, please leave a comment on the issue you want to contribute to before starting to work on it.
If you found this library helpful, you can support me by giving a small tip via GitHub Sponsors and/or joining the list of stargazers by leaving a star! 🌟
Copyright [2024 - Present] starry-shivam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.