diff --git a/src/commonMain/kotlin/com/insanusmokrassar/krontab/Executes.kt b/src/commonMain/kotlin/com/insanusmokrassar/krontab/Executes.kt index e0934d2..6c2fe51 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/krontab/Executes.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/krontab/Executes.kt @@ -1,25 +1,32 @@ package com.insanusmokrassar.krontab -suspend inline fun CronDateTimeScheduler.executeInfinity(noinline block: suspend () -> Unit) = doInLoop { +import com.soywiz.klock.DateTime +import kotlinx.coroutines.delay + +suspend inline fun KronScheduler.doWhile(noinline block: suspend () -> Boolean) { + do { + delay(next().unixMillisLong - DateTime.now().unixMillisLong) + } while (block()) +} +suspend inline fun doWhile( + scheduleConfig: String, + noinline block: suspend () -> Boolean +) = createSimpleScheduler(scheduleConfig).doWhile(block) + +suspend inline fun KronScheduler.doInfinity(noinline block: suspend () -> Unit) = doWhile { block() true } -suspend inline fun executeInfinity( +suspend inline fun doInfinity( scheduleConfig: String, noinline block: suspend () -> Unit -) = createCronDateTimeScheduler(scheduleConfig).executeInfinity(block) +) = createSimpleScheduler(scheduleConfig).doInfinity(block) -suspend inline fun CronDateTimeScheduler.executeWhile(noinline block: suspend () -> Boolean) = doInLoop(block) -suspend inline fun executeWhile( - scheduleConfig: String, - noinline block: suspend () -> Boolean -) = createCronDateTimeScheduler(scheduleConfig).executeWhile(block) - -suspend inline fun CronDateTimeScheduler.executeOnce(noinline block: suspend () -> Unit) = doInLoop { +suspend inline fun KronScheduler.doOnce(noinline block: suspend () -> Unit) = doWhile { block() false } -suspend inline fun executeOnce( +suspend inline fun doOnce( scheduleConfig: String, noinline block: suspend () -> Unit -) = createCronDateTimeScheduler(scheduleConfig).executeOnce(block) +) = createSimpleScheduler(scheduleConfig).doOnce(block) diff --git a/src/commonMain/kotlin/com/insanusmokrassar/krontab/KronScheduler.kt b/src/commonMain/kotlin/com/insanusmokrassar/krontab/KronScheduler.kt new file mode 100644 index 0000000..b4ea91f --- /dev/null +++ b/src/commonMain/kotlin/com/insanusmokrassar/krontab/KronScheduler.kt @@ -0,0 +1,7 @@ +package com.insanusmokrassar.krontab + +import com.soywiz.klock.DateTime + +interface KronScheduler { + suspend fun next(relatively: DateTime = DateTime.now()): DateTime +} diff --git a/src/commonMain/kotlin/com/insanusmokrassar/krontab/SchedulerShortcuts.kt b/src/commonMain/kotlin/com/insanusmokrassar/krontab/SchedulerShortcuts.kt index 92871eb..5688e24 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/krontab/SchedulerShortcuts.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/krontab/SchedulerShortcuts.kt @@ -6,24 +6,24 @@ import com.insanusmokrassar.krontab.internal.CronDateTime internal val anyCronDateTime by lazy { CronDateTime() } -val AnyTimeScheduler by lazy { +val AnyTimeScheduler: KronScheduler by lazy { CronDateTimeScheduler(listOf(anyCronDateTime)) } -val EverySecondScheduler +val EverySecondScheduler: KronScheduler get() = AnyTimeScheduler -val EveryMinuteScheduler by lazy { +val EveryMinuteScheduler: KronScheduler by lazy { buildSchedule { minutes { 0 every 1 } } } -val EveryHourScheduler by lazy { +val EveryHourScheduler: KronScheduler by lazy { buildSchedule { hours { 0 every 1 } } } -val EveryDayOfMonthScheduler by lazy { +val EveryDayOfMonthScheduler: KronScheduler by lazy { buildSchedule { dayOfMonth { 0 every 1 } } } -val EveryMonthScheduler by lazy { +val EveryMonthScheduler: KronScheduler by lazy { buildSchedule { months { 0 every 1 } } } \ No newline at end of file diff --git a/src/commonMain/kotlin/com/insanusmokrassar/krontab/CronDateTimeScheduler.kt b/src/commonMain/kotlin/com/insanusmokrassar/krontab/StringParser.kt similarity index 50% rename from src/commonMain/kotlin/com/insanusmokrassar/krontab/CronDateTimeScheduler.kt rename to src/commonMain/kotlin/com/insanusmokrassar/krontab/StringParser.kt index ad2cc95..1e9063f 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/krontab/CronDateTimeScheduler.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/krontab/StringParser.kt @@ -1,25 +1,39 @@ package com.insanusmokrassar.krontab import com.insanusmokrassar.krontab.internal.* -import com.soywiz.klock.DateTime -import kotlinx.coroutines.delay +import com.insanusmokrassar.krontab.internal.CronDateTime +import com.insanusmokrassar.krontab.internal.parseDaysOfMonth +import com.insanusmokrassar.krontab.internal.parseHours +import com.insanusmokrassar.krontab.internal.parseMinutes +import com.insanusmokrassar.krontab.internal.parseMonths +import com.insanusmokrassar.krontab.internal.parseSeconds -data class CronDateTimeScheduler internal constructor( - internal val cronDateTimes: List -) - -fun CronDateTimeScheduler.next(relatively: DateTime = DateTime.now()): DateTime { - return cronDateTimes.map { it.toNearDateTime(relatively) }.min() ?: anyCronDateTime.toNearDateTime(relatively) -} - -suspend fun CronDateTimeScheduler.doInLoop(block: suspend () -> Boolean) { - do { - delay(next().unixMillisLong - DateTime.now().unixMillisLong) - } while (block()) -} - - -fun createCronDateTimeScheduler(incoming: String): CronDateTimeScheduler { +/** + * Parse [incoming] string and adapt according to next format: "* * * * *" where order of things: + * + * seconds + * minutes + * hours + * dayOfMonth + * month + * + * And each one have next format: + * + * {number},{number},... + * + * and {number} here is one of {int}-{int} OR {int}/{int} OR *\/{int} OR {int}. + * + * Seconds ranges can be found in [com.insanusmokrassar.krontab.internal.secondsRange]. + * Minutes ranges can be found in [com.insanusmokrassar.krontab.internal.minutesRange]. + * Hours ranges can be found in [com.insanusmokrassar.krontab.internal.hoursRange]. + * Days of month ranges can be found in [com.insanusmokrassar.krontab.internal.dayOfMonthRange]. + * Months ranges can be found in [com.insanusmokrassar.krontab.internal.monthRange]. + * + * @sample "0/5 * * * *" for every five seconds triggering + * @sample "0/15 30 * * *" for every 15th seconds in a half of each hour + * @sample "1 2 3 4 5" for triggering in near first second of second minute of third hour of fourth day of may + */ +fun createSimpleScheduler(incoming: String): KronScheduler { val (secondsSource, minutesSource, hoursSource, dayOfMonthSource, monthSource) = incoming.split(" ") val secondsParsed = parseSeconds(secondsSource) @@ -51,4 +65,4 @@ fun createCronDateTimeScheduler(incoming: String): CronDateTimeScheduler { } return CronDateTimeScheduler(resultCronDateTimes.toList()) -} +} \ No newline at end of file diff --git a/src/commonMain/kotlin/com/insanusmokrassar/krontab/builder/SchedulerBuilder.kt b/src/commonMain/kotlin/com/insanusmokrassar/krontab/builder/SchedulerBuilder.kt index c52a9a4..7beb38f 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/krontab/builder/SchedulerBuilder.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/krontab/builder/SchedulerBuilder.kt @@ -1,10 +1,11 @@ package com.insanusmokrassar.krontab.builder import com.insanusmokrassar.krontab.CronDateTimeScheduler +import com.insanusmokrassar.krontab.KronScheduler import com.insanusmokrassar.krontab.internal.CronDateTime import com.insanusmokrassar.krontab.internal.fillWith -fun buildSchedule(settingsBlock: SchedulerBuilder.() -> Unit): CronDateTimeScheduler { +fun buildSchedule(settingsBlock: SchedulerBuilder.() -> Unit): KronScheduler { val builder = SchedulerBuilder() builder.settingsBlock() @@ -75,7 +76,7 @@ class SchedulerBuilder( ) } - fun build(): CronDateTimeScheduler { + fun build(): KronScheduler { val resultCronDateTimes = mutableListOf(CronDateTime()) seconds ?.fillWith(resultCronDateTimes) { previousCronDateTime: CronDateTime, currentTime: Byte -> diff --git a/src/commonMain/kotlin/com/insanusmokrassar/krontab/internal/CronDateTimeScheduler.kt b/src/commonMain/kotlin/com/insanusmokrassar/krontab/internal/CronDateTimeScheduler.kt new file mode 100644 index 0000000..68351ea --- /dev/null +++ b/src/commonMain/kotlin/com/insanusmokrassar/krontab/internal/CronDateTimeScheduler.kt @@ -0,0 +1,13 @@ +package com.insanusmokrassar.krontab + +import com.insanusmokrassar.krontab.internal.* +import com.soywiz.klock.DateTime + +internal data class CronDateTimeScheduler internal constructor( + internal val cronDateTimes: List +) : KronScheduler { + override suspend fun next(relatively: DateTime): DateTime { + return cronDateTimes.map { it.toNearDateTime(relatively) }.min() ?: anyCronDateTime.toNearDateTime(relatively) + } +} + diff --git a/src/commonMain/kotlin/com/insanusmokrassar/krontab/internal/Parser.kt b/src/commonMain/kotlin/com/insanusmokrassar/krontab/internal/Parser.kt index b10b8fd..dd152eb 100644 --- a/src/commonMain/kotlin/com/insanusmokrassar/krontab/internal/Parser.kt +++ b/src/commonMain/kotlin/com/insanusmokrassar/krontab/internal/Parser.kt @@ -2,7 +2,7 @@ package com.insanusmokrassar.krontab.internal import com.insanusmokrassar.krontab.utils.clamp -private fun createCronDateTimeScheduler(from: String, dataRange: IntRange): Array? { +private fun createSimpleScheduler(from: String, dataRange: IntRange): Array? { val things = from.split(",") val results = things.flatMap { @@ -25,21 +25,11 @@ private fun createCronDateTimeScheduler(from: String, dataRange: IntRange): Arra return results.map { it.toByte() }.toTypedArray() } -internal fun parseMonths(from: String) = createCronDateTimeScheduler(from, - com.insanusmokrassar.krontab.internal.monthRange -) -internal fun parseDaysOfMonth(from: String) = createCronDateTimeScheduler(from, - com.insanusmokrassar.krontab.internal.dayOfMonthRange -) -internal fun parseHours(from: String) = createCronDateTimeScheduler(from, - com.insanusmokrassar.krontab.internal.hoursRange -) -internal fun parseMinutes(from: String) = createCronDateTimeScheduler(from, - com.insanusmokrassar.krontab.internal.minutesRange -) -internal fun parseSeconds(from: String) = createCronDateTimeScheduler(from, - com.insanusmokrassar.krontab.internal.secondsRange -) +internal fun parseMonths(from: String) = createSimpleScheduler(from, monthRange) +internal fun parseDaysOfMonth(from: String) = createSimpleScheduler(from, dayOfMonthRange) +internal fun parseHours(from: String) = createSimpleScheduler(from, hoursRange) +internal fun parseMinutes(from: String) = createSimpleScheduler(from, minutesRange) +internal fun parseSeconds(from: String) = createSimpleScheduler(from, secondsRange) internal fun Array.fillWith( whereToPut: MutableList,