delay in doWhile and flows with doWhile instead their own logic

This commit is contained in:
InsanusMokrassar 2021-09-25 19:28:49 +06:00
parent 539b5fbcd8
commit 4dc65bf09a
3 changed files with 87 additions and 21 deletions

View File

@ -2,6 +2,9 @@
## 0.6.5
* Flows now use `doWhile` functions
* `doWhile` now use additional delay (for 1 ms) for cases when `block` executing too fast
## 0.6.4
* Versions

View File

@ -1,8 +1,23 @@
package dev.inmo.krontab
import com.soywiz.klock.DateTime
import com.soywiz.klock.DateTimeTz
import kotlinx.coroutines.delay
/**
* 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 immediately
*/
suspend inline fun <T> KronSchedulerTz.doOnce(noinline block: suspend () -> T): T {
nextTimeZoned() ?.let {
delay((it - DateTimeTz.nowLocal()).millisecondsLong)
}
return block()
}
/**
* Execute [block] once at the [KronScheduler.next] time and return result of [block] calculation.
*
@ -24,13 +39,31 @@ suspend inline fun <T> KronScheduler.doOnce(noinline block: suspend () -> T): T
suspend inline fun <T> doOnce(
scheduleConfig: String,
noinline block: suspend () -> T
) = buildSchedule(scheduleConfig).doOnce(block)
) = with(buildSchedule(scheduleConfig)) {
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.doWhile(noinline block: suspend () -> Boolean) {
do { val doNext = doOnce(block) } while (doNext)
do {
delay(1L)
val doNext = doOnce(block)
} while (doNext)
}
/**
* Will execute [block] while it will return true as a result of its calculation
*/
suspend inline fun KronSchedulerTz.doWhile(noinline block: suspend () -> Boolean) {
do {
delay(1L)
val doNext = doOnce(block)
} while (doNext)
}
/**
@ -41,7 +74,12 @@ suspend inline fun KronScheduler.doWhile(noinline block: suspend () -> Boolean)
suspend inline fun doWhile(
scheduleConfig: String,
noinline block: suspend () -> Boolean
) = buildSchedule(scheduleConfig).doWhile(block)
) = with(buildSchedule(scheduleConfig)) {
when (this) {
is KronSchedulerTz -> doWhile(block)
else -> doWhile(block)
}
}
/**
* Will execute [block] without any checking of result
@ -50,6 +88,14 @@ suspend inline fun KronScheduler.doInfinity(noinline block: suspend () -> Unit)
block()
true
}
/**
* Will execute [block] without any checking of result
*/
suspend inline fun KronSchedulerTz.doInfinity(noinline block: suspend () -> Unit) = doWhile {
block()
true
}
/**
* Will [buildSchedule] using [scheduleConfig] and call [doInfinity] with [block]
*
@ -58,4 +104,9 @@ suspend inline fun KronScheduler.doInfinity(noinline block: suspend () -> Unit)
suspend inline fun doInfinity(
scheduleConfig: String,
noinline block: suspend () -> Unit
) = buildSchedule(scheduleConfig).doInfinity(block)
) = with(buildSchedule(scheduleConfig)) {
when (this) {
is KronSchedulerTz -> doInfinity(block)
else -> doInfinity(block)
}
}

View File

@ -2,8 +2,7 @@ package dev.inmo.krontab.utils
import com.soywiz.klock.DateTime
import com.soywiz.klock.DateTimeTz
import dev.inmo.krontab.KronScheduler
import dev.inmo.krontab.next
import dev.inmo.krontab.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
@ -12,30 +11,43 @@ import kotlinx.coroutines.flow.*
* time zones
*
* @see channelFlow
* @see KronSchedulerTz.doWhile
*/
@FlowPreview
fun KronScheduler.asTzFlow(): Flow<DateTimeTz> = channelFlow {
var previousTime = DateTime.nowLocal()
while (isActive) {
val now = DateTime.nowLocal()
val nextTime = next(now) ?: break
if (previousTime == nextTime) {
delay(1L) // skip 1ms
continue
} else {
previousTime = nextTime
}
val sleepDelay = (nextTime - DateTime.now().local).millisecondsLong
delay(sleepDelay)
send(nextTime)
fun KronSchedulerTz.asTzFlow(): Flow<DateTimeTz> = channelFlow {
doWhile {
send(DateTime.nowLocal())
isActive
}
}
/**
* This method is a map for [asTzFlow] and will works the same but return flow with [DateTime]s
*
* @see channelFlow
* @see KronScheduler.doWhile
*/
@FlowPreview
fun KronScheduler.asFlow(): Flow<DateTime> = asTzFlow().map { it.local }
fun KronScheduler.asFlow(): Flow<DateTime> = channelFlow {
doWhile {
send(DateTime.now())
isActive
}
}
/**
* This [Flow] will trigger emitting each near time which will be returned from [this] [KronScheduler] with attention to
* time zones
*
* @see channelFlow
* @see KronScheduler.asFlow
* @see KronSchedulerTz.asTzFlow
*/
@FlowPreview
fun KronScheduler.asTzFlow(): Flow<DateTimeTz> = when (this) {
is KronSchedulerTz -> asTzFlow()
else -> asFlow().map { it.local }
}
@Deprecated(
"It is not recommended to use this class in future. This functionality will be removed soon",