mirror of
https://github.com/InsanusMokrassar/krontab.git
synced 2025-12-05 04:25:48 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e5bbea84d9 | |||
| a01a18a6d1 | |||
| 132986d275 | |||
| 04118902e8 | |||
| 96857aa7bc | |||
| f8b677406f | |||
| 53f34f0a27 | |||
| 989780243a | |||
| 7b5417ccc5 | |||
| 2004a7dd05 | |||
| 7c4217bda6 | |||
| 3d6fee7257 | |||
| 6cec25eca0 | |||
| a0972eaff9 | |||
| cc75501b04 | |||
| 89e500ff33 | |||
| a61cd61602 | |||
|
|
5fdb2ea049 | ||
| 68ed562b19 | |||
| 87b5dfe1aa | |||
| 6a6bfe0552 | |||
| ede47ae664 | |||
| 890ab5b15d | |||
| 5a1ed2f933 | |||
| 7da67386cf | |||
| 7027719fe5 | |||
| a81c7c7c3f | |||
|
|
e5658998d4 | ||
| 6b3cb981ab |
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,5 +1,38 @@
|
||||
# Changelog
|
||||
|
||||
## 2.1.0
|
||||
|
||||
* Versions
|
||||
* `Kotlin`: `1.8.22`
|
||||
* `Klock`: `4.0.3`
|
||||
* New value class `KrontabConfig`. It is preferable way to create `KronScheduler` instead of
|
||||
`KrontabTemplate` since this update
|
||||
* You may configure krontab with builders using simple `KronScheduler` invoke extension
|
||||
* New useful extensions like `KronScheduler.daily`
|
||||
* `KrontabTemplateWrapper` is obsolete in favor to `KrontabConfig`
|
||||
|
||||
## 2.0.0
|
||||
|
||||
* Versions
|
||||
* `Kotlin`: `1.8.21`
|
||||
* `Klock`: `4.0.1`
|
||||
* Support of `mingwx64` platform
|
||||
|
||||
## 1.0.0
|
||||
|
||||
* Versions
|
||||
* `Kotlin`: `1.8.20`
|
||||
* `AndroidXWork`: `2.8.1`
|
||||
|
||||
## 0.10.0
|
||||
|
||||
* New extensions for `KronScheduler`:
|
||||
* `asTzFlowWithoutDelays`/`asFlowWithoutDelays`
|
||||
* `asTzFlowWithDelays`/`asFlowWithDelays`
|
||||
* Old `KronScheduler.asFlow` and `KronScheduler.asTzFlow` temporarily marked as deprecated: after several versions their
|
||||
behaviour will be changed to undelayed one
|
||||
* All the flow extensions now use `cold` non-channel flows. Potentially it should increase performance and decrease memory usage
|
||||
|
||||
## 0.9.0
|
||||
|
||||
* Versions
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
[](https://insanusmokrassar.github.io/krontab/)
|
||||
[](https://bookstack.inmo.dev/books/krontab)
|
||||
[](https://docs.inmo.dev/krontab/index.html)
|
||||
|
||||
Library was created to give oppotunity to launch some things from time to time according to some schedule in
|
||||
runtime of applications.
|
||||
@@ -26,7 +27,7 @@ Anyway, to start some action from time to time you will need to use one of exten
|
||||
```kotlin
|
||||
val kronScheduler = /* creating of KronScheduler instance */;
|
||||
|
||||
kronScheuler.doWhile {
|
||||
kronScheduler.doWhile {
|
||||
// some action
|
||||
true // true - repeat on next time
|
||||
}
|
||||
|
||||
11
build.gradle
11
build.gradle
@@ -8,14 +8,16 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
classpath "com.github.breadmoirai:github-release:$github_release_plugin_version"
|
||||
classpath "com.getkeepsafe.dexcount:dexcount-gradle-plugin:$dexcount_version"
|
||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
||||
classpath "com.android.tools.build:gradle:$android_gradle_version"
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version"
|
||||
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
|
||||
id "org.jetbrains.dokka" version "$dokka_version"
|
||||
}
|
||||
|
||||
@@ -57,6 +59,8 @@ kotlin {
|
||||
android {
|
||||
publishAllLibraryVariants()
|
||||
}
|
||||
linuxX64()
|
||||
mingwX64()
|
||||
|
||||
|
||||
sourceSets {
|
||||
@@ -64,6 +68,7 @@ kotlin {
|
||||
dependencies {
|
||||
implementation kotlin('stdlib')
|
||||
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
|
||||
api "org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlin_serialization_version"
|
||||
|
||||
api "com.soywiz.korlibs.klock:klock:$klockVersion"
|
||||
}
|
||||
@@ -79,6 +84,7 @@ kotlin {
|
||||
dependencies {
|
||||
implementation kotlin('test-common')
|
||||
implementation kotlin('test-annotations-common')
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlin_coroutines_version"
|
||||
}
|
||||
}
|
||||
jvmTest {
|
||||
@@ -102,8 +108,9 @@ kotlin {
|
||||
apply plugin: 'com.getkeepsafe.dexcount'
|
||||
|
||||
android {
|
||||
compileSdkVersion "$android_compileSdkVersion".toInteger()
|
||||
compileSdk "$android_compileSdkVersion".toInteger()
|
||||
buildToolsVersion "$android_buildToolsVersion"
|
||||
namespace "${group}.${project.name}"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion "$android_minSdkVersion".toInteger()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx512m
|
||||
kotlin.code.style=official
|
||||
org.gradle.parallel=true
|
||||
kotlin.js.generate.externals=true
|
||||
@@ -8,12 +9,13 @@ android.useAndroidX=true
|
||||
android.enableJetifier=false
|
||||
|
||||
|
||||
kotlin_version=1.8.10
|
||||
kotlin_version=1.8.22
|
||||
kotlin_coroutines_version=1.6.4
|
||||
kotlin_serialization_version=1.5.1
|
||||
|
||||
dokka_version=1.7.20
|
||||
dokka_version=1.8.20
|
||||
|
||||
klockVersion=3.4.0
|
||||
klockVersion=4.0.3
|
||||
|
||||
## Github reease
|
||||
|
||||
@@ -21,17 +23,18 @@ github_release_plugin_version=2.4.1
|
||||
|
||||
## Android
|
||||
|
||||
android_gradle_version=7.4.2
|
||||
android_minSdkVersion=21
|
||||
android_compileSdkVersion=33
|
||||
android_buildToolsVersion=33.0.1
|
||||
dexcount_version=3.1.0
|
||||
android_buildToolsVersion=33.0.2
|
||||
dexcount_version=4.0.0
|
||||
junit_version=4.12
|
||||
test_ext_junit_version=1.1.3
|
||||
espresso_core=3.4.0
|
||||
|
||||
androidx_work_version=2.8.0
|
||||
androidx_work_version=2.8.1
|
||||
|
||||
## Common
|
||||
|
||||
version=0.9.0
|
||||
android_code_version=23
|
||||
version=2.1.0
|
||||
android_code_version=27
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
|
||||
|
||||
6
renovate.json
Normal file
6
renovate.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.krontab
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.DateTimeTz
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.DateTimeTz
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import korlibs.time.DateTime
|
||||
|
||||
/**
|
||||
* This interface was created for abstraction of [next] operation. Currently, there is only
|
||||
@@ -18,6 +18,8 @@ interface KronScheduler {
|
||||
* @see dev.inmo.krontab.internal.CronDateTimeScheduler.next
|
||||
*/
|
||||
suspend fun next(relatively: DateTime = DateTime.now()): DateTime?
|
||||
|
||||
companion object
|
||||
}
|
||||
|
||||
suspend fun KronScheduler.nextOrRelative(relatively: DateTime = DateTime.now()): DateTime = next(relatively) ?: getAnyNext(relatively)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.krontab
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.DateTimeTz
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.DateTimeTz
|
||||
|
||||
/**
|
||||
* This interface extending [KronScheduler] to use [DateTimeTz] with taking into account offset of incoming time for
|
||||
|
||||
165
src/commonMain/kotlin/dev/inmo/krontab/KrontabConfig.kt
Normal file
165
src/commonMain/kotlin/dev/inmo/krontab/KrontabConfig.kt
Normal file
@@ -0,0 +1,165 @@
|
||||
package dev.inmo.krontab
|
||||
|
||||
import dev.inmo.krontab.internal.CronDateTimeScheduler
|
||||
import dev.inmo.krontab.internal.CronDateTimeSchedulerTz
|
||||
import dev.inmo.krontab.internal.createKronScheduler
|
||||
import dev.inmo.krontab.internal.createKronSchedulerWithOffset
|
||||
import dev.inmo.krontab.internal.millisecondsArrayDefault
|
||||
import dev.inmo.krontab.internal.parseDaysOfMonth
|
||||
import dev.inmo.krontab.internal.parseHours
|
||||
import dev.inmo.krontab.internal.parseMilliseconds
|
||||
import dev.inmo.krontab.internal.parseMinutes
|
||||
import dev.inmo.krontab.internal.parseMonths
|
||||
import dev.inmo.krontab.internal.parseOffset
|
||||
import dev.inmo.krontab.internal.parseSeconds
|
||||
import dev.inmo.krontab.internal.parseWeekDay
|
||||
import dev.inmo.krontab.internal.parseYears
|
||||
import dev.inmo.krontab.utils.Minutes
|
||||
import korlibs.time.TimezoneOffset
|
||||
import korlibs.time.minutes
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
/**
|
||||
* This value class contains [KrontabTemplate]
|
||||
*
|
||||
* * **seconds**
|
||||
* * **minutes**
|
||||
* * **hours**
|
||||
* * **dayOfMonth**
|
||||
* * **month**
|
||||
* * **year** (optional)
|
||||
* * **offset** (optional) (can be placed anywhere after month) (must be marked with `o` at the end, for example: 60o == +01:00)
|
||||
* * **dayOfWeek** (optional) (can be placed anywhere after month)
|
||||
* * **milliseconds** (optional) (can be placed anywhere after month) (must be marked with `ms` at the end, for example: 500ms; 100-200ms)
|
||||
*
|
||||
* And each one (except of offsets) have next format:
|
||||
*
|
||||
* `{number}[,{number},...]` or `*`
|
||||
*
|
||||
* and {number} here is one of
|
||||
*
|
||||
* * {int}-{int}
|
||||
* * {int}/{int}
|
||||
* * */{int}
|
||||
* * {int}
|
||||
* * F
|
||||
* * L
|
||||
*
|
||||
* Week days must be marked with `w` at the end, and starts with 0 which means Sunday. For example, 0w == Sunday. With
|
||||
* weeks you can use syntax like with any number like seconds, for example: 0-2w means Sunday-Tuesday
|
||||
*
|
||||
* Additional info about ranges can be found in follow accordance:
|
||||
*
|
||||
* * Seconds ranges can be found in [secondsRange]
|
||||
* * Minutes ranges can be found in [minutesRange]
|
||||
* * Hours ranges can be found in [hoursRange]
|
||||
* * Days of month ranges can be found in [dayOfMonthRange]
|
||||
* * Months ranges can be found in [monthRange]
|
||||
* * Years ranges can be found in [yearRange] (in fact - any [Int])
|
||||
* * WeekDay (timezone) ranges can be found in [dayOfWeekRange]
|
||||
* * Milliseconds ranges can be found in [millisecondsRange]
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* * "0/5 * * * *" for every five seconds triggering
|
||||
* * "0/5,L * * * *" for every five seconds triggering and on 59 second
|
||||
* * "0/15 30 * * *" for every 15th seconds in a half of each hour
|
||||
* * "0/15 30 * * * 500ms" for every 15th seconds in a half of each hour when milliseconds equal to 500
|
||||
* * "1 2 3 F,4,L 5" for triggering in near first second of second minute of third hour of first, fifth and last days of may
|
||||
* * "1 2 3 F,4,L 5 60o" for triggering in near first second of second minute of third hour of first, fifth and last days of may with timezone UTC+01:00
|
||||
* * "1 2 3 F,4,L 5 60o 0-2w" for triggering in near first second of second minute of third hour of first, fifth and last days of may in case if it will be in Sunday-Tuesday week days with timezone UTC+01:00
|
||||
* * "1 2 3 F,4,L 5 2021" for triggering in near first second of second minute of third hour of first, fifth and last days of may of 2021st year
|
||||
* * "1 2 3 F,4,L 5 2021 60o" for triggering in near first second of second minute of third hour of first, fifth and last days of may of 2021st year with timezone UTC+01:00
|
||||
* * "1 2 3 F,4,L 5 2021 60o 0-2w" for triggering in near first second of second minute of third hour of first, fifth and last days of may of 2021st year if it will be in Sunday-Tuesday week days with timezone UTC+01:00
|
||||
* * "1 2 3 F,4,L 5 2021 60o 0-2w 500ms" for triggering in near first second of second minute of third hour of first, fifth and last days of may of 2021st year if it will be in Sunday-Tuesday week days with timezone UTC+01:00 when milliseconds will be equal to 500
|
||||
*
|
||||
* @see dev.inmo.krontab.internal.createKronScheduler
|
||||
*/
|
||||
@Serializable
|
||||
@JvmInline
|
||||
value class KrontabConfig(
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
val template: KrontabTemplate
|
||||
) {
|
||||
/**
|
||||
* Creates __new__ [KronScheduler] based on a [template]
|
||||
*
|
||||
* @return In case when offset parameter is absent in [template] will be used [createSimpleScheduler] method and
|
||||
* returned [CronDateTimeScheduler]. In case when offset parameter there is in [template] [KrontabTemplate] will be used
|
||||
* [createKronSchedulerWithOffset] and returned [CronDateTimeSchedulerTz]
|
||||
*/
|
||||
fun scheduler(): KronScheduler {
|
||||
var offsetParsed: Int? = null
|
||||
var dayOfWeekParsed: Array<Byte>? = null
|
||||
var yearParsed: Array<Int>? = null
|
||||
var millisecondsParsed: Array<Short>? = null
|
||||
val (secondsSource, minutesSource, hoursSource, dayOfMonthSource, monthSource) = template.split(" ").also {
|
||||
listOfNotNull(
|
||||
it.getOrNull(5),
|
||||
it.getOrNull(6),
|
||||
it.getOrNull(7),
|
||||
it.getOrNull(8)
|
||||
).forEach {
|
||||
val offsetFromString = parseOffset(it)
|
||||
val dayOfWeekFromString = parseWeekDay(it)
|
||||
val millisecondsFromString = parseMilliseconds(it)
|
||||
offsetParsed = offsetParsed ?: offsetFromString
|
||||
dayOfWeekParsed = dayOfWeekParsed ?: dayOfWeekFromString
|
||||
millisecondsParsed = millisecondsParsed ?: millisecondsFromString
|
||||
when {
|
||||
dayOfWeekFromString != null || offsetFromString != null || millisecondsFromString != null -> return@forEach
|
||||
yearParsed == null -> {
|
||||
yearParsed = parseYears(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val secondsParsed = parseSeconds(secondsSource)
|
||||
val minutesParsed = parseMinutes(minutesSource)
|
||||
val hoursParsed = parseHours(hoursSource)
|
||||
val dayOfMonthParsed = parseDaysOfMonth(dayOfMonthSource)
|
||||
val monthParsed = parseMonths(monthSource)
|
||||
|
||||
return offsetParsed ?.let { offset ->
|
||||
createKronSchedulerWithOffset(
|
||||
secondsParsed,
|
||||
minutesParsed,
|
||||
hoursParsed,
|
||||
dayOfMonthParsed,
|
||||
monthParsed,
|
||||
yearParsed,
|
||||
dayOfWeekParsed,
|
||||
TimezoneOffset(offset.minutes),
|
||||
millisecondsParsed ?: millisecondsArrayDefault
|
||||
)
|
||||
} ?: createKronScheduler(
|
||||
secondsParsed,
|
||||
minutesParsed,
|
||||
hoursParsed,
|
||||
dayOfMonthParsed,
|
||||
monthParsed,
|
||||
yearParsed,
|
||||
dayOfWeekParsed,
|
||||
millisecondsParsed ?: millisecondsArrayDefault
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates base [KronScheduler] using [scheduler] function. In case when returned [KronScheduler] is [KronSchedulerTz],
|
||||
* it will be returned as is. Otherwise, will be created new [CronDateTimeSchedulerTz] with [defaultOffset] as
|
||||
* offset
|
||||
*/
|
||||
fun scheduler(defaultOffset: Minutes): KronSchedulerTz {
|
||||
val scheduler = scheduler()
|
||||
return if (scheduler is KronSchedulerTz) {
|
||||
scheduler
|
||||
} else {
|
||||
CronDateTimeSchedulerTz(
|
||||
(scheduler as CronDateTimeScheduler).cronDateTime,
|
||||
TimezoneOffset(defaultOffset.minutes)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,10 @@ package dev.inmo.krontab
|
||||
* [dev.inmo.krontab.internal.CronDateTimeScheduler] due to the fact that [toKronScheduler] will return it under the
|
||||
* hood
|
||||
*/
|
||||
@Deprecated(
|
||||
"It is useless wrapper for KrontabTemplate. Use KrontabConfig instead",
|
||||
ReplaceWith("KrontabConfig(template)", "dev.inmo.krontab.KrontabConfig")
|
||||
)
|
||||
data class KrontabTemplateWrapper(
|
||||
val template: KrontabTemplate
|
||||
) : KronScheduler by template.toKronScheduler()
|
||||
@@ -15,4 +19,8 @@ data class KrontabTemplateWrapper(
|
||||
* @see [toKronScheduler]
|
||||
* @see [KrontabTemplateWrapper]
|
||||
*/
|
||||
@Deprecated(
|
||||
"Will be removed in near major update with KrontabTemplateWrapper",
|
||||
ReplaceWith("this.krontabConfig", "dev.inmo.krontab.krontabConfig")
|
||||
)
|
||||
fun KrontabTemplate.wrapAsKronScheduler() = KrontabTemplateWrapper(this)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import korlibs.time.DateTime
|
||||
|
||||
class LambdaKronScheduler(
|
||||
private val onNext: suspend (DateTime) -> DateTime?
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab
|
||||
|
||||
import com.soywiz.klock.DateTimeTz
|
||||
import korlibs.time.DateTimeTz
|
||||
|
||||
class LambdaKronSchedulerTz(
|
||||
private val onNext: suspend (DateTimeTz) -> DateTimeTz?
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import korlibs.time.DateTime
|
||||
import dev.inmo.krontab.builder.buildSchedule
|
||||
import dev.inmo.krontab.internal.*
|
||||
|
||||
@@ -10,57 +10,99 @@ internal val anyCronDateTime by lazy {
|
||||
internal fun getAnyNext(relatively: DateTime) = anyCronDateTime.toNearDateTime(relatively)!!
|
||||
|
||||
/**
|
||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now]
|
||||
* [KronScheduler.next] will always return [korlibs.time.DateTime.now]
|
||||
*/
|
||||
val AnyTimeScheduler: KronScheduler by lazy {
|
||||
CronDateTimeScheduler(anyCronDateTime)
|
||||
}
|
||||
|
||||
/**
|
||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] + one millisecond
|
||||
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one millisecond
|
||||
*/
|
||||
val EveryMillisecondScheduler: KronScheduler by lazy {
|
||||
buildSchedule { milliseconds { 0 every 1 } }
|
||||
}
|
||||
|
||||
/**
|
||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] + one second
|
||||
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one second
|
||||
*/
|
||||
val EverySecondScheduler: KronScheduler by lazy {
|
||||
buildSchedule { seconds { 0 every 1 } }
|
||||
}
|
||||
|
||||
/**
|
||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] + one minute
|
||||
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one minute
|
||||
*/
|
||||
val EveryMinuteScheduler: KronScheduler by lazy {
|
||||
buildSchedule { minutes { 0 every 1 } }
|
||||
}
|
||||
|
||||
/**
|
||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] + one hour
|
||||
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one hour
|
||||
*/
|
||||
val EveryHourScheduler: KronScheduler by lazy {
|
||||
buildSchedule { hours { 0 every 1 } }
|
||||
}
|
||||
|
||||
/**
|
||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] + one day
|
||||
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one day
|
||||
*/
|
||||
val EveryDayOfMonthScheduler: KronScheduler by lazy {
|
||||
buildSchedule { dayOfMonth { 0 every 1 } }
|
||||
}
|
||||
|
||||
/**
|
||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] + one month
|
||||
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one month
|
||||
*/
|
||||
val EveryMonthScheduler: KronScheduler by lazy {
|
||||
buildSchedule { months { 0 every 1 } }
|
||||
}
|
||||
|
||||
/**
|
||||
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] + one year
|
||||
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one year
|
||||
*/
|
||||
val EveryYearScheduler: KronScheduler by lazy {
|
||||
buildSchedule { years { 0 every 1 } }
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for [EveryMillisecondScheduler]
|
||||
*/
|
||||
inline val KronScheduler.Companion.everyMillisecond
|
||||
get() = EveryMillisecondScheduler
|
||||
|
||||
/**
|
||||
* Shortcut for [EverySecondScheduler]
|
||||
*/
|
||||
inline val KronScheduler.Companion.everySecond
|
||||
get() = EverySecondScheduler
|
||||
|
||||
/**
|
||||
* Shortcut for [EveryMinuteScheduler]
|
||||
*/
|
||||
inline val KronScheduler.Companion.everyMinute
|
||||
get() = EveryMinuteScheduler
|
||||
|
||||
/**
|
||||
* Shortcut for [EveryHourScheduler]
|
||||
*/
|
||||
inline val KronScheduler.Companion.hourly
|
||||
get() = EveryHourScheduler
|
||||
|
||||
/**
|
||||
* Shortcut for [EveryDayOfMonthScheduler]
|
||||
*/
|
||||
inline val KronScheduler.Companion.daily
|
||||
get() = EveryDayOfMonthScheduler
|
||||
|
||||
/**
|
||||
* Shortcut for [EveryMonthScheduler]
|
||||
*/
|
||||
inline val KronScheduler.Companion.monthly
|
||||
get() = EveryMonthScheduler
|
||||
|
||||
/**
|
||||
* Shortcut for [EveryYearScheduler]
|
||||
*/
|
||||
inline val KronScheduler.Companion.annually
|
||||
get() = EveryYearScheduler
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package dev.inmo.krontab
|
||||
|
||||
import com.soywiz.klock.TimezoneOffset
|
||||
import com.soywiz.klock.minutes
|
||||
import dev.inmo.krontab.internal.*
|
||||
import dev.inmo.krontab.utils.Minutes
|
||||
|
||||
@@ -11,6 +9,8 @@ import dev.inmo.krontab.utils.Minutes
|
||||
*/
|
||||
typealias KrontabTemplate = String
|
||||
|
||||
inline fun KrontabTemplate.krontabConfig() = KrontabConfig(this)
|
||||
|
||||
/**
|
||||
* Parse [incoming] string and adapt according to next format: "* * * * *" where order of things:
|
||||
*
|
||||
@@ -70,80 +70,16 @@ typealias KrontabTemplate = String
|
||||
* [createKronSchedulerWithOffset] and returned [CronDateTimeSchedulerTz]
|
||||
*
|
||||
* @see dev.inmo.krontab.internal.createKronScheduler
|
||||
* @see KrontabConfig.scheduler
|
||||
*/
|
||||
fun createSimpleScheduler(
|
||||
incoming: KrontabTemplate
|
||||
): KronScheduler {
|
||||
var offsetParsed: Int? = null
|
||||
var dayOfWeekParsed: Array<Byte>? = null
|
||||
var yearParsed: Array<Int>? = null
|
||||
var millisecondsParsed: Array<Short>? = null
|
||||
val (secondsSource, minutesSource, hoursSource, dayOfMonthSource, monthSource) = incoming.split(" ").also {
|
||||
listOfNotNull(
|
||||
it.getOrNull(5),
|
||||
it.getOrNull(6),
|
||||
it.getOrNull(7),
|
||||
it.getOrNull(8)
|
||||
).forEach {
|
||||
val offsetFromString = parseOffset(it)
|
||||
val dayOfWeekFromString = parseWeekDay(it)
|
||||
val millisecondsFromString = parseMilliseconds(it)
|
||||
offsetParsed = offsetParsed ?: offsetFromString
|
||||
dayOfWeekParsed = dayOfWeekParsed ?: dayOfWeekFromString
|
||||
millisecondsParsed = millisecondsParsed ?: millisecondsFromString
|
||||
when {
|
||||
dayOfWeekFromString != null || offsetFromString != null || millisecondsFromString != null -> return@forEach
|
||||
yearParsed == null -> {
|
||||
yearParsed = parseYears(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val secondsParsed = parseSeconds(secondsSource)
|
||||
val minutesParsed = parseMinutes(minutesSource)
|
||||
val hoursParsed = parseHours(hoursSource)
|
||||
val dayOfMonthParsed = parseDaysOfMonth(dayOfMonthSource)
|
||||
val monthParsed = parseMonths(monthSource)
|
||||
|
||||
return offsetParsed ?.let { offset ->
|
||||
createKronSchedulerWithOffset(
|
||||
secondsParsed,
|
||||
minutesParsed,
|
||||
hoursParsed,
|
||||
dayOfMonthParsed,
|
||||
monthParsed,
|
||||
yearParsed,
|
||||
dayOfWeekParsed,
|
||||
TimezoneOffset(offset.minutes),
|
||||
millisecondsParsed ?: millisecondsArrayDefault
|
||||
)
|
||||
} ?: createKronScheduler(
|
||||
secondsParsed,
|
||||
minutesParsed,
|
||||
hoursParsed,
|
||||
dayOfMonthParsed,
|
||||
monthParsed,
|
||||
yearParsed,
|
||||
dayOfWeekParsed,
|
||||
millisecondsParsed ?: millisecondsArrayDefault
|
||||
)
|
||||
}
|
||||
): KronScheduler = KrontabConfig(incoming).scheduler()
|
||||
|
||||
fun createSimpleScheduler(
|
||||
incoming: KrontabTemplate,
|
||||
defaultOffset: Minutes
|
||||
): KronSchedulerTz {
|
||||
val scheduler = createSimpleScheduler(incoming)
|
||||
return if (scheduler is KronSchedulerTz) {
|
||||
scheduler
|
||||
} else {
|
||||
CronDateTimeSchedulerTz(
|
||||
(scheduler as CronDateTimeScheduler).cronDateTime,
|
||||
TimezoneOffset(defaultOffset.minutes)
|
||||
)
|
||||
}
|
||||
}
|
||||
): KronSchedulerTz = KrontabConfig(incoming).scheduler(defaultOffset)
|
||||
|
||||
/**
|
||||
* Shortcut for [createSimpleScheduler]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.krontab.builder
|
||||
|
||||
import com.soywiz.klock.TimezoneOffset
|
||||
import com.soywiz.klock.minutes
|
||||
import korlibs.time.TimezoneOffset
|
||||
import korlibs.time.minutes
|
||||
import dev.inmo.krontab.KronScheduler
|
||||
import dev.inmo.krontab.KronSchedulerTz
|
||||
import dev.inmo.krontab.internal.*
|
||||
@@ -14,7 +14,7 @@ import dev.inmo.krontab.utils.Minutes
|
||||
*
|
||||
* @see dev.inmo.krontab.createSimpleScheduler
|
||||
*/
|
||||
fun buildSchedule(settingsBlock: SchedulerBuilder.() -> Unit): KronScheduler {
|
||||
inline fun buildSchedule(settingsBlock: SchedulerBuilder.() -> Unit): KronScheduler {
|
||||
val builder = SchedulerBuilder()
|
||||
|
||||
builder.settingsBlock()
|
||||
@@ -27,7 +27,7 @@ fun buildSchedule(settingsBlock: SchedulerBuilder.() -> Unit): KronScheduler {
|
||||
*
|
||||
* @see dev.inmo.krontab.createSimpleScheduler
|
||||
*/
|
||||
fun buildSchedule(
|
||||
inline fun buildSchedule(
|
||||
offset: Minutes,
|
||||
settingsBlock: SchedulerBuilder.() -> Unit
|
||||
): KronSchedulerTz {
|
||||
@@ -38,6 +38,27 @@ fun buildSchedule(
|
||||
return builder.build() as KronSchedulerTz
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new [KronScheduler] with [settingsBlock]
|
||||
*
|
||||
* Since it is inline function, you may break execution of [settingsBlock]
|
||||
* at any time
|
||||
*/
|
||||
inline operator fun KronScheduler.Companion.invoke(
|
||||
offset: Minutes,
|
||||
settingsBlock: SchedulerBuilder.() -> Unit
|
||||
): KronSchedulerTz = buildSchedule(offset, settingsBlock)
|
||||
|
||||
/**
|
||||
* Creates new [KronScheduler] with [settingsBlock]
|
||||
*
|
||||
* Since it is inline function, you may break execution of [settingsBlock]
|
||||
* at any time
|
||||
*/
|
||||
inline operator fun KronScheduler.Companion.invoke(
|
||||
settingsBlock: SchedulerBuilder.() -> Unit
|
||||
): KronScheduler = buildSchedule(settingsBlock)
|
||||
|
||||
class SchedulerBuilder(
|
||||
private var seconds: Array<Byte>? = null,
|
||||
private var minutes: Array<Byte>? = null,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.krontab.collection
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.DateTimeTz
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.DateTimeTz
|
||||
import dev.inmo.krontab.*
|
||||
import dev.inmo.krontab.internal.*
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.krontab.internal
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.TimezoneOffset
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.TimezoneOffset
|
||||
import dev.inmo.krontab.KronScheduler
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab.internal
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import korlibs.time.DateTime
|
||||
import dev.inmo.krontab.KronScheduler
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package dev.inmo.krontab.internal
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.DateTimeTz
|
||||
import com.soywiz.klock.TimezoneOffset
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.DateTimeTz
|
||||
import korlibs.time.TimezoneOffset
|
||||
import dev.inmo.krontab.KronScheduler
|
||||
import dev.inmo.krontab.KronSchedulerTz
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab.internal
|
||||
|
||||
import com.soywiz.klock.*
|
||||
import korlibs.time.*
|
||||
import dev.inmo.krontab.utils.copy
|
||||
import kotlin.math.min
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.Month
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.Month
|
||||
import kotlin.math.min
|
||||
|
||||
fun DateTime.copy(
|
||||
|
||||
@@ -1,36 +1,91 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.DateTimeTz
|
||||
import dev.inmo.krontab.*
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.DateTimeTz
|
||||
import korlibs.time.milliseconds
|
||||
import dev.inmo.krontab.KronScheduler
|
||||
import dev.inmo.krontab.next
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.isActive
|
||||
|
||||
/**
|
||||
* This [Flow] will trigger emitting each near time which will be returned from [this] [KronScheduler] with attention to
|
||||
* time zones
|
||||
* **This flow is [cold](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)**
|
||||
*
|
||||
* @see channelFlow
|
||||
* @see KronSchedulerTz.doInfinityTz
|
||||
* Will emit all the [KronScheduler.next] as soon as possible. In case [KronScheduler.next] return null, flow will
|
||||
* be completed
|
||||
*
|
||||
* @param since Will be used as the first parameter for [KronScheduler.next] fun
|
||||
*/
|
||||
@FlowPreview
|
||||
fun KronScheduler.asTzFlow(): Flow<DateTimeTz> = channelFlow {
|
||||
doInfinityTz {
|
||||
send(it)
|
||||
fun KronScheduler.asTzFlowWithoutDelays(since: DateTimeTz = DateTime.nowLocal()): Flow<DateTimeTz> = flow {
|
||||
var previous = since
|
||||
while (currentCoroutineContext().isActive) {
|
||||
val next = next(previous) ?: break
|
||||
emit(next)
|
||||
previous = next + 1.milliseconds
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a map for [asTzFlow] and will works the same but return flow with [DateTime]s
|
||||
* **This flow is [cold](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)**
|
||||
*
|
||||
* @see channelFlow
|
||||
* @see KronScheduler.doInfinity
|
||||
* This [Flow] will use [asTzFlowWithoutDelays], but stop on each time until this time will happen
|
||||
*/
|
||||
@FlowPreview
|
||||
fun KronScheduler.asFlow(): Flow<DateTime> = channelFlow {
|
||||
doInfinity {
|
||||
send(it)
|
||||
fun KronScheduler.asTzFlowWithDelays(): Flow<DateTimeTz> = asTzFlowWithoutDelays().onEach { futureHappenTime ->
|
||||
val now = DateTime.nowLocal()
|
||||
|
||||
delay((futureHappenTime - now).millisecondsLong)
|
||||
}
|
||||
|
||||
/**
|
||||
* **This flow is [cold](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)**
|
||||
*
|
||||
* This [Flow] will use [asTzFlowWithoutDelays], but stop on each time until this time will happen
|
||||
*/
|
||||
@Deprecated(
|
||||
"Behaviour will be changed. In some of near versions this flow will not delay executions",
|
||||
ReplaceWith("this.asTzFlowWithDelays()", "dev.inmo.krontab.utils.asTzFlowWithDelays")
|
||||
)
|
||||
fun KronScheduler.asTzFlow(): Flow<DateTimeTz> = asTzFlowWithDelays()
|
||||
|
||||
/**
|
||||
* **This flow is [cold](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)**
|
||||
*
|
||||
* Will emit all the [KronScheduler.next] as soon as possible. In case [KronScheduler.next] return null, flow will
|
||||
* be completed
|
||||
*
|
||||
* @param since Will be used as the first parameter for [KronScheduler.next] fun
|
||||
*/
|
||||
fun KronScheduler.asFlowWithoutDelays(since: DateTime = DateTime.now()): Flow<DateTime> = flow {
|
||||
var previous = since
|
||||
while (currentCoroutineContext().isActive) {
|
||||
val next = next(previous) ?: break
|
||||
emit(next)
|
||||
previous = next + 1.milliseconds
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* **This flow is [cold](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)**
|
||||
*
|
||||
* This [Flow] will use [asFlowWithoutDelays], but stop on each time until this time will happen
|
||||
*/
|
||||
fun KronScheduler.asFlowWithDelays(): Flow<DateTime> = asFlowWithoutDelays().onEach { futureHappenTime ->
|
||||
val now = DateTime.now()
|
||||
|
||||
delay((futureHappenTime - now).millisecondsLong)
|
||||
}
|
||||
|
||||
/**
|
||||
* **This flow is [cold](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/)**
|
||||
*
|
||||
* This [Flow] will use [asFlowWithDelays], but stop on each time until this time will happen
|
||||
*/
|
||||
@Deprecated(
|
||||
"Behaviour will be changed. In some of near versions this flow will not delay executions",
|
||||
ReplaceWith("this.asFlowWithDelays()", "dev.inmo.krontab.utils.asFlowWithDelays")
|
||||
)
|
||||
fun KronScheduler.asFlow(): Flow<DateTime> = asFlowWithDelays()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab.utils.flows
|
||||
|
||||
import com.soywiz.klock.*
|
||||
import korlibs.time.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab.utils.flows
|
||||
|
||||
import com.soywiz.klock.*
|
||||
import korlibs.time.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab.utils.flows
|
||||
|
||||
import com.soywiz.klock.*
|
||||
import korlibs.time.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dev.inmo.krontab.utils.flows
|
||||
|
||||
import com.soywiz.klock.*
|
||||
import korlibs.time.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import com.soywiz.klock.days
|
||||
import korlibs.time.DateTime
|
||||
import korlibs.time.days
|
||||
import dev.inmo.krontab.buildSchedule
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlin.test.*
|
||||
|
||||
class CheckMonthsAndDaysCorrectWork {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
fun CoroutineScope.createFailJob(forTimeMillis: Long) = launch {
|
||||
delay(forTimeMillis)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
/**
|
||||
* Workaround to use suspending functions in unit tests
|
||||
*/
|
||||
expect fun runTest(block: suspend (scope : CoroutineScope) -> Unit)
|
||||
@@ -2,8 +2,8 @@ package dev.inmo.krontab.utils
|
||||
|
||||
import dev.inmo.krontab.builder.buildSchedule
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@@ -18,7 +18,7 @@ class SchedulerFlowTests {
|
||||
}
|
||||
}
|
||||
|
||||
val flow = kronScheduler.asFlow()
|
||||
val flow = kronScheduler.asFlowWithoutDelays()
|
||||
|
||||
runTest {
|
||||
val mustBeCollected = 10
|
||||
@@ -40,14 +40,14 @@ class SchedulerFlowTests {
|
||||
}
|
||||
}
|
||||
|
||||
val flow = kronScheduler.asFlow()
|
||||
val flow = kronScheduler.asFlowWithoutDelays()
|
||||
|
||||
runTest {
|
||||
val testsCount = 10
|
||||
val failJob = it.createFailJob((testsCount * 2) * 1000L)
|
||||
val failJob = createFailJob((testsCount * 2) * 1000L)
|
||||
val mustBeCollected = 10
|
||||
val answers = (0 until testsCount).map { _ ->
|
||||
it.async {
|
||||
async {
|
||||
var collected = 0
|
||||
flow.takeWhile {
|
||||
collected < mustBeCollected
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import com.soywiz.klock.*
|
||||
import korlibs.time.*
|
||||
import dev.inmo.krontab.KronSchedulerTz
|
||||
import dev.inmo.krontab.buildSchedule
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlin.math.floor
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlin.test.*
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@@ -16,7 +15,7 @@ class StringParseTest {
|
||||
fun testThatFlowIsCorrectlyWorkEverySecondBuiltOnString() {
|
||||
val kronScheduler = buildSchedule("*/1 * * * *")
|
||||
|
||||
val flow = kronScheduler.asFlow()
|
||||
val flow = kronScheduler.asFlowWithoutDelays()
|
||||
|
||||
runTest {
|
||||
val mustBeCollected = 10
|
||||
@@ -33,7 +32,7 @@ class StringParseTest {
|
||||
fun testThatFlowIsCorrectlyWorkEverySecondWhenMillisIsHalfOfSecondBuiltOnString() {
|
||||
val kronScheduler = buildSchedule("*/1 * * * * 500ms")
|
||||
|
||||
val flow = kronScheduler.asFlow()
|
||||
val flow = kronScheduler.asFlowWithoutDelays()
|
||||
|
||||
runTest {
|
||||
val mustBeCollected = 10
|
||||
@@ -51,14 +50,14 @@ class StringParseTest {
|
||||
fun testThatFlowIsCorrectlyWorkEverySecondWithMuchOfEmittersBuiltOnString() {
|
||||
val kronScheduler = buildSchedule("*/1 * * * *")
|
||||
|
||||
val flow = kronScheduler.asFlow()
|
||||
val flow = kronScheduler.asFlowWithoutDelays()
|
||||
|
||||
runTest {
|
||||
val testsCount = 10
|
||||
val failJob = it.createFailJob((testsCount * 2) * 1000L)
|
||||
val failJob = createFailJob((testsCount * 2) * 1000L)
|
||||
val mustBeCollected = 10
|
||||
val answers = (0 until testsCount).map { _ ->
|
||||
it.async {
|
||||
async {
|
||||
var collected = 0
|
||||
flow.takeWhile {
|
||||
collected < mustBeCollected
|
||||
@@ -81,7 +80,7 @@ class StringParseTest {
|
||||
val rangesEnds = listOf(0 to 5, 30 to 35)
|
||||
val kronScheduler = buildSchedule("${rangesEnds.joinToString(",") { "${it.first}-${it.second}" }} * * * *")
|
||||
|
||||
val flow = kronScheduler.asFlow()
|
||||
val flow = kronScheduler.asFlowWithoutDelays()
|
||||
|
||||
runTest {
|
||||
val ranges = rangesEnds.map { it.first .. it.second }.flatten().distinct().toMutableList()
|
||||
@@ -91,7 +90,10 @@ class StringParseTest {
|
||||
flow.takeWhile { ranges.isNotEmpty() }.collect {
|
||||
ranges.remove(it.seconds)
|
||||
collected++
|
||||
assertTrue(collected <= expectedCollects)
|
||||
assertTrue(
|
||||
collected <= expectedCollects,
|
||||
"Expected value should be less than $expectedCollects, but was $collected. Ranges state: $ranges"
|
||||
)
|
||||
}
|
||||
assertEquals(expectedCollects, collected)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import com.soywiz.klock.*
|
||||
import korlibs.time.*
|
||||
import dev.inmo.krontab.builder.buildSchedule
|
||||
import dev.inmo.krontab.next
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import com.soywiz.klock.*
|
||||
import korlibs.time.*
|
||||
import dev.inmo.krontab.builder.buildSchedule
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlin.math.ceil
|
||||
import kotlin.test.*
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
actual fun runTest(block: suspend (scope : CoroutineScope) -> Unit): dynamic = GlobalScope.promise { block(this) }
|
||||
@@ -1,9 +0,0 @@
|
||||
package dev.inmo.krontab.utils
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
/**
|
||||
* Workaround to use suspending functions in unit tests
|
||||
*/
|
||||
actual fun runTest(block: suspend (scope: CoroutineScope) -> Unit) = runBlocking(block = block)
|
||||
@@ -1 +0,0 @@
|
||||
<manifest package="dev.inmo.krontab"/>
|
||||
@@ -2,7 +2,7 @@ package dev.inmo.krontab
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.*
|
||||
import com.soywiz.klock.DateTime
|
||||
import korlibs.time.DateTime
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user