overwrite do* extensions

This commit is contained in:
InsanusMokrassar 2021-09-26 13:05:59 +06:00
parent d36e406b59
commit 276ecaac27
3 changed files with 143 additions and 52 deletions

View File

@ -4,6 +4,7 @@
* Flows now use `doWhile` functions * Flows now use `doWhile` functions
* `doWhile` now use additional delay (for 1 ms) for cases when `block` executing too fast * `doWhile` now use additional delay (for 1 ms) for cases when `block` executing too fast
* New extensions for `KronScheduler`: `do(Once/While/Infinity)Local`/`do(Once/While/Infinity)Tz`
## 0.6.4 ## 0.6.4

View File

@ -7,16 +7,6 @@
Library was created to give oppotunity to launch some things from time to time according to some schedule in Library was created to give oppotunity to launch some things from time to time according to some schedule in
runtime of applications. runtime of applications.
| Table of content |
|---|
| [ How to use ](#how-to-use) |
| [ How to use: Including in project ](#including-in-project) |
| [ How to use: Config from string ](#config-from-string) |
| [ How to use: Config via builder (DSL preview) ](#config-via-builder) |
| [ How to use: KronScheduler as a Flow ](#KronScheduler-as-a-Flow) |
| [ How to use: Offsets ](#Offsets) |
| [ How to use: Note about week days ](#Note-about-week-days) |
## How to use ## How to use
There are several ways to configure and use this library: There are several ways to configure and use this library:
@ -133,6 +123,38 @@ kronScheduler.doInfinity {
All of these examples will do the same things: print `Called` message every five seconds. All of these examples will do the same things: print `Called` message every five seconds.
### do\* functions
With regular `doOnce`/`doWhile`/`doInfinity` there are two types of their variations: **local** and **timezoned**. Local
variations (`doOnceLocal`/`doWhileLocal`/`doInfinityLocal`) will pass `DateTime` as an argument into the block:
```kotlin
doInfinityLocal("/5 * * * *") {
println(it) // will print current date time
}
```
Timezoned variations (`doOnceTz`/`doWhileTz`/`doInfinityTz`) will do the same thing but pass as an argument `DateTimeTz`:
```kotlin
doInfinityTz("/5 * * * * 0o") {
println(it) // will print current date time in UTC
}
```
It is useful in cases when you need to get the time of calling and avoid extra calls to system time.
#### Helpful table for
| | No args | Local `DateTime` | Local `DateTimeTz` with offset of `KronScheduler` |
|---| ------- | ---------------- | ------------------------------------------------- |
| **Call only near time** | doOnce | doOnceLocal | doOnceTz |
| **Call while condition is true** | doWhile | doWhileLocal | doWhileTz |
| **Work infinity*** | doInfinity | doInfinityLocal | doInfinityTz |
*Here there is an important notice, that `Work infinity` is not exactly `infinity`. Actually, that means that `do while
coroutine is alive` and in fact executing will be stopped when coroutine became cancelled.
### KronScheduler as a Flow ### KronScheduler as a Flow
Any `KronScheduler`can e converted to a `Flow<DateTime` using extension `asFlow`: Any `KronScheduler`can e converted to a `Flow<DateTime` using extension `asFlow`:
@ -163,7 +185,7 @@ flow.takeWhile {
Offsets in this library works via passing parameter ending with `o` in any place after `month` config. Currently Offsets in this library works via passing parameter ending with `o` in any place after `month` config. Currently
there is only one format supported for offsets: minutes of offsets. To use time zones you will need to call `next` there is only one format supported for offsets: minutes of offsets. To use time zones you will need to call `next`
method with `DateTimeTz` argument or `nextTimeZoned` method with any `KronScheduler` instance, but in case if this method with `DateTimeTz` argument or `nextTimeZoned` method with any `KronScheduler` instance, but in case if this
scheduler is not instance of `KronSchedulerTz` it will works like you passed just `DateTime`. scheduler is not instance of `KronSchedulerTz` it will work like you passed just `DateTime`.
Besides, in case you wish to use time zones explicitly, you will need to get `KronSchedulerTz`. It is possible by: Besides, in case you wish to use time zones explicitly, you will need to get `KronSchedulerTz`. It is possible by:

View File

@ -13,11 +13,27 @@ import kotlin.coroutines.coroutineContext
* *
* WARNING!!! In case if [KronScheduler.next] of [this] instance will return null, [block] will be called immediately * WARNING!!! In case if [KronScheduler.next] of [this] instance will return null, [block] will be called immediately
*/ */
suspend inline fun <T> KronSchedulerTz.doOnce(noinline block: suspend () -> T): T { suspend inline fun <T> KronScheduler.doOnceLocal(noinline block: suspend (DateTime) -> T): T {
nextTimeZoned() ?.let { val time = nextOrNow().also {
delay((it - DateTimeTz.nowLocal()).millisecondsLong) delay((it - DateTime.now()).millisecondsLong)
} }
return block() return block(time)
}
/**
* Execute [block] once at the [KronScheduler.next] time and return result of [block] calculation.
*
* WARNING!!! If you want to launch it in parallel, you must do this explicitly.
*
* WARNING!!! In case if [KronScheduler.next] of [this] instance will return null, [block] will be called immediatelly
*/
suspend inline fun <T> KronScheduler.doOnceTz(noinline block: suspend (DateTimeTz) -> T): T {
val time = when (this) {
is KronSchedulerTz -> nextOrNowWithOffset()
else -> nextOrNow().local
}
delay((time - DateTimeTz.nowLocal()).millisecondsLong)
return block(time)
} }
/** /**
@ -27,46 +43,78 @@ suspend inline fun <T> KronSchedulerTz.doOnce(noinline block: suspend () -> T):
* *
* WARNING!!! In case if [KronScheduler.next] of [this] instance will return null, [block] will be called immediately * WARNING!!! In case if [KronScheduler.next] of [this] instance will return null, [block] will be called immediately
*/ */
suspend inline fun <T> KronScheduler.doOnce(noinline block: suspend () -> T): T { suspend inline fun <T> KronScheduler.doOnce(noinline block: suspend () -> T): T = doOnceLocal { _ -> block() }
next() ?.let {
delay((it - DateTime.now()).millisecondsLong)
}
return block()
}
/** /**
* Will [buildSchedule] using [scheduleConfig] and call [doOnce] on it * Will [buildSchedule] using [scheduleConfig] and call [doOnceLocal] on it
* @see buildSchedule
*/
suspend inline fun <T> doOnce(
scheduleConfig: String,
noinline block: suspend (DateTime) -> T
) = buildSchedule(scheduleConfig).doOnceLocal(block)
/**
* Will [buildSchedule] using [scheduleConfig] and call [doOnceLocal] on it
* @see buildSchedule
*/
suspend inline fun <T> doOnceTz(
scheduleConfig: String,
noinline block: suspend (DateTimeTz) -> T
) = buildSchedule(scheduleConfig).doOnceTz(block)
/**
* Will [buildSchedule] using [scheduleConfig] and call [doOnceLocal] on it
* @see buildSchedule * @see buildSchedule
*/ */
suspend inline fun <T> doOnce( suspend inline fun <T> doOnce(
scheduleConfig: String, scheduleConfig: String,
noinline block: suspend () -> T noinline block: suspend () -> T
) = with(buildSchedule(scheduleConfig)) { ) = doOnce(scheduleConfig) { _ -> block() }
when (this) {
is KronSchedulerTz -> doOnce(block)
else -> doOnce(block) /**
} * Will execute [block] while it will return true as a result of its calculation
*/
suspend inline fun KronScheduler.doWhileLocal(noinline block: suspend (DateTime) -> Boolean) {
do {
delay(1L)
} while (doOnceLocal(block))
} }
/** /**
* Will execute [block] while it will return true as a result of its calculation * Will execute [block] while it will return true as a result of its calculation
*/ */
suspend inline fun KronScheduler.doWhile(noinline block: suspend () -> Boolean) { suspend inline fun KronScheduler.doWhileTz(noinline block: suspend (DateTimeTz) -> Boolean) {
do { do {
delay(1L) delay(1L)
val doNext = doOnce(block) } while (doOnceTz(block))
} while (doNext)
} }
/** /**
* Will execute [block] while it will return true as a result of its calculation * Will execute [block] while it will return true as a result of its calculation
*/ */
suspend inline fun KronSchedulerTz.doWhile(noinline block: suspend () -> Boolean) { suspend inline fun KronScheduler.doWhile(noinline block: suspend () -> Boolean) = doWhileLocal { block() }
do {
delay(1L) /**
val doNext = doOnce(block) * Will [buildSchedule] using [scheduleConfig] and call [doWhile] with [block]
} while (doNext) *
} * @see buildSchedule
*/
suspend inline fun doWhileLocal(
scheduleConfig: String,
noinline block: suspend (DateTime) -> Boolean
) = buildSchedule(scheduleConfig).doWhileLocal(block)
/**
* Will [buildSchedule] using [scheduleConfig] and call [doWhile] with [block]
*
* @see buildSchedule
*/
suspend inline fun doWhileTz(
scheduleConfig: String,
noinline block: suspend (DateTimeTz) -> Boolean
) = buildSchedule(scheduleConfig).doWhileTz(block)
/** /**
* Will [buildSchedule] using [scheduleConfig] and call [doWhile] with [block] * Will [buildSchedule] using [scheduleConfig] and call [doWhile] with [block]
@ -76,11 +124,23 @@ suspend inline fun KronSchedulerTz.doWhile(noinline block: suspend () -> Boolean
suspend inline fun doWhile( suspend inline fun doWhile(
scheduleConfig: String, scheduleConfig: String,
noinline block: suspend () -> Boolean noinline block: suspend () -> Boolean
) = with(buildSchedule(scheduleConfig)) { ) = doWhileLocal(scheduleConfig) { block() }
when (this) {
is KronSchedulerTz -> doWhile(block)
else -> doWhile(block) /**
} * Will execute [block] without any checking of result
*/
suspend inline fun KronScheduler.doInfinityLocal(noinline block: suspend (DateTime) -> Unit) = doWhileLocal {
block(it)
coroutineContext.isActive
}
/**
* Will execute [block] without any checking of result
*/
suspend inline fun KronScheduler.doInfinityTz(noinline block: suspend (DateTimeTz) -> Unit) = doWhileTz {
block(it)
coroutineContext.isActive
} }
/** /**
@ -92,12 +152,25 @@ suspend inline fun KronScheduler.doInfinity(noinline block: suspend () -> Unit)
} }
/** /**
* Will execute [block] without any checking of result * Will [buildSchedule] using [scheduleConfig] and call [doInfinity] with [block]
*
* @see buildSchedule
*/ */
suspend inline fun KronSchedulerTz.doInfinity(noinline block: suspend () -> Unit) = doWhile { suspend inline fun doInfinityLocal(
block() scheduleConfig: String,
coroutineContext.isActive noinline block: suspend (DateTime) -> Unit
} ) = buildSchedule(scheduleConfig).doInfinityLocal(block)
/**
* Will [buildSchedule] using [scheduleConfig] and call [doInfinity] with [block]
*
* @see buildSchedule
*/
suspend inline fun doInfinityTz(
scheduleConfig: String,
noinline block: suspend (DateTimeTz) -> Unit
) = buildSchedule(scheduleConfig).doInfinityTz(block)
/** /**
* Will [buildSchedule] using [scheduleConfig] and call [doInfinity] with [block] * Will [buildSchedule] using [scheduleConfig] and call [doInfinity] with [block]
* *
@ -106,9 +179,4 @@ suspend inline fun KronSchedulerTz.doInfinity(noinline block: suspend () -> Unit
suspend inline fun doInfinity( suspend inline fun doInfinity(
scheduleConfig: String, scheduleConfig: String,
noinline block: suspend () -> Unit noinline block: suspend () -> Unit
) = with(buildSchedule(scheduleConfig)) { ) = buildSchedule(scheduleConfig).doInfinity(block)
when (this) {
is KronSchedulerTz -> doInfinity(block)
else -> doInfinity(block)
}
}