Compare commits

...

93 Commits

Author SHA1 Message Date
InsanusMokrassar f90d8d03d9
Merge pull request #108 from InsanusMokrassar/2.3.0
2.3.0
2024-04-25 18:44:04 +06:00
InsanusMokrassar 36671cb379 potential fix of #107 2024-03-21 17:34:22 +06:00
InsanusMokrassar 68be768763 start 2.3.0 2024-03-21 17:14:59 +06:00
InsanusMokrassar 9546eb5aec
Merge pull request #103 from InsanusMokrassar/2.2.9
2.2.9
2024-03-16 16:06:32 +06:00
InsanusMokrassar 2efd7e6157 fixes in built-in schedulers 2024-03-16 15:56:45 +06:00
InsanusMokrassar 6845537afd remove redundant change of KronSchedulerWork.kt 2024-03-16 10:31:12 +06:00
InsanusMokrassar af28fce6f5 update dependencies 2024-03-06 20:01:41 +06:00
InsanusMokrassar 237b42c2d3 start 2.2.9 2024-03-06 19:36:42 +06:00
InsanusMokrassar 49f852f27e
Merge pull request #101 from InsanusMokrassar/renovate/dokka_version
Update plugin org.jetbrains.dokka to v1.9.20
2024-03-05 13:56:26 +06:00
renovate[bot] 470dc92f54
Update plugin org.jetbrains.dokka to v1.9.20 2024-03-05 02:59:24 +00:00
InsanusMokrassar b5dcdc185f
Merge pull request #99 from InsanusMokrassar/2.2.8
2.2.8
2024-02-18 22:24:34 +06:00
InsanusMokrassar 8df9f9c086 update dependencies 2024-02-18 22:14:01 +06:00
InsanusMokrassar 484f46223f start 2.2.8 2024-02-18 21:56:06 +06:00
InsanusMokrassar 1ce654fa06
Merge pull request #94 from InsanusMokrassar/2.2.7
2.2.7
2024-01-31 17:56:23 +06:00
InsanusMokrassar 6da04f54da update dependencies 2024-01-31 17:40:15 +06:00
InsanusMokrassar e1d716688a start 2.2.7 2024-01-31 17:26:48 +06:00
InsanusMokrassar e247de9e24
Merge pull request #92 from InsanusMokrassar/2.2.6
2.2.6
2024-01-12 14:52:32 +06:00
InsanusMokrassar a153bc7996 update klock 2024-01-12 14:45:14 +06:00
InsanusMokrassar 9753cda961 start 2.2.6 2024-01-12 14:33:22 +06:00
InsanusMokrassar e8ef6e6935 update publication script 2023-12-28 15:51:33 +06:00
InsanusMokrassar b41bf0ea07
Merge pull request #91 from InsanusMokrassar/2.2.5
2.2.5
2023-12-28 15:47:39 +06:00
InsanusMokrassar 09d811e2c4
Update CHANGELOG.md 2023-12-28 15:47:27 +06:00
InsanusMokrassar 3faadefced update dependencies 2023-12-27 19:15:35 +06:00
InsanusMokrassar f3883a8678 start 2.2.5 2023-12-27 01:14:50 +06:00
InsanusMokrassar 5ff02a2a9d
Merge pull request #85 from InsanusMokrassar/2.2.4
2.2.4
2023-11-26 21:23:18 +06:00
InsanusMokrassar f56215ee10 start 2.2.4 and update dependencies 2023-11-26 21:20:39 +06:00
InsanusMokrassar e66acb34de
Update kdocs.yml 2023-11-03 00:31:23 +06:00
InsanusMokrassar 78ac446311
Update publishing_packages.yml 2023-11-03 00:31:12 +06:00
InsanusMokrassar 697b4e81b8
Merge pull request #81 from InsanusMokrassar/2.2.3
2.2.3
2023-11-02 23:28:22 +06:00
InsanusMokrassar d1288de032 build fixes 2023-11-02 23:27:53 +06:00
InsanusMokrassar eb867e7366 update dependencies and gradle environment 2023-11-02 23:22:19 +06:00
InsanusMokrassar 4aa10e00cf start 2.2.3 2023-11-02 23:19:24 +06:00
InsanusMokrassar 170d443517
Merge pull request #80 from InsanusMokrassar/2.2.2
2.2.2
2023-10-23 01:27:57 +06:00
InsanusMokrassar d1aab7ccd6 add arm target 2023-10-23 01:27:19 +06:00
InsanusMokrassar 58d758f141 Update gradle-wrapper.properties 2023-10-23 01:27:19 +06:00
InsanusMokrassar 71bd3f0eb4 update dependencies 2023-10-23 01:27:19 +06:00
InsanusMokrassar bd2a852b16 start 2.2.2 2023-10-23 01:27:19 +06:00
InsanusMokrassar 8e844b5875 update kotlinx serialization 2023-10-23 01:26:17 +06:00
InsanusMokrassar e0f7dddf42 update dependencies 2023-10-23 01:26:17 +06:00
InsanusMokrassar d64acc9806 potential fix of #65 2023-10-23 01:26:17 +06:00
InsanusMokrassar 58375452c7 start 2.2.1 2023-10-23 01:26:17 +06:00
InsanusMokrassar cbfbdc1b33 files replacements 2023-08-09 13:01:20 +06:00
InsanusMokrassar 715d414f51 update dependencies 2023-08-09 12:35:13 +06:00
InsanusMokrassar 2ecd8c4292 start 2.2.0 2023-08-09 12:24:41 +06:00
InsanusMokrassar 1be8d947f7
Merge pull request #67 from InsanusMokrassar/2.1.2
2.1.2
2023-07-05 20:07:15 +06:00
InsanusMokrassar f66c1c2477 remove redundant change in string parse change 2023-07-05 20:05:39 +06:00
InsanusMokrassar 69cf7afd4e make inline functions callbacks inline again 2023-07-02 16:41:52 +06:00
InsanusMokrassar 92df91edd3 update coroutines 2023-07-02 16:06:47 +06:00
InsanusMokrassar f7a388f438 start 2.1.2 2023-07-02 16:05:46 +06:00
InsanusMokrassar 9a10c7eb87
Merge pull request #64 from InsanusMokrassar/2.1.1
2.1.1
2023-06-20 11:44:13 +06:00
InsanusMokrassar d67be582af nullable since in asFlowWithoutDelays and asTzFlowWithoutDelays 2023-06-20 11:35:57 +06:00
InsanusMokrassar 171bb687ea start 2.1.1 2023-06-20 11:26:57 +06:00
InsanusMokrassar 7807d10121
Merge pull request #63 from InsanusMokrassar/2.1.0
2.1.0
2023-06-20 10:42:01 +06:00
InsanusMokrassar e5bbea84d9 update changelog and kdocs 2023-06-20 10:41:46 +06:00
InsanusMokrassar a01a18a6d1 KrontabTemplateWrapper deprecation, extensions like "daily" 2023-06-20 10:25:15 +06:00
InsanusMokrassar 132986d275 migration onto 2.1.0 2023-06-20 10:13:03 +06:00
InsanusMokrassar 04118902e8 KrontabConfig, KronScheduler.Companion and its builders extensions 2023-06-20 10:12:32 +06:00
InsanusMokrassar 96857aa7bc update dependencies 2023-06-20 09:45:07 +06:00
InsanusMokrassar f8b677406f start 2.0.1 2023-06-20 09:43:04 +06:00
InsanusMokrassar 53f34f0a27
Update README.md 2023-06-10 18:16:53 +06:00
InsanusMokrassar 989780243a update dokka 2023-06-09 12:10:41 +06:00
InsanusMokrassar 7b5417ccc5
Merge pull request #58 from InsanusMokrassar/2.0.0
2.0.0
2023-05-25 21:19:39 +06:00
InsanusMokrassar 2004a7dd05 update changelog 2023-05-25 20:53:58 +06:00
InsanusMokrassar 7c4217bda6 migration onto new klock and fixes in android manifest 2023-05-25 20:53:10 +06:00
InsanusMokrassar 3d6fee7257 migrate onto 2.0.0 due to changes in klock 2023-05-25 20:50:48 +06:00
InsanusMokrassar 6cec25eca0 update kotlin version 2023-05-25 20:41:33 +06:00
InsanusMokrassar a0972eaff9 start 1.1.0 2023-05-25 20:38:51 +06:00
InsanusMokrassar cc75501b04
Merge pull request #49 from InsanusMokrassar/1.0.0
1.0.0
2023-04-25 00:28:01 +06:00
InsanusMokrassar 89e500ff33
Merge pull request #48 from InsanusMokrassar/renovate/configure
Configure Renovate
2023-04-25 00:15:38 +06:00
InsanusMokrassar a61cd61602 update dependencies 2023-04-25 00:15:13 +06:00
renovate[bot] 5fdb2ea049
Add renovate.json 2023-04-24 18:11:35 +00:00
InsanusMokrassar 68ed562b19 start 1.0.0 2023-04-25 00:10:11 +06:00
InsanusMokrassar 87b5dfe1aa
Update README.md 2023-04-03 16:18:18 +06:00
InsanusMokrassar 6a6bfe0552
Merge pull request #47 from InsanusMokrassar/0.10.0
0.10.0
2023-03-18 14:01:14 +06:00
InsanusMokrassar ede47ae664 remove redundant FlowPrevies on flows API 2023-03-18 12:34:06 +06:00
InsanusMokrassar 890ab5b15d fill changelogs 2023-03-18 12:24:25 +06:00
InsanusMokrassar 5a1ed2f933 start 0.10.0 + rework of flows 2023-03-18 12:23:53 +06:00
InsanusMokrassar 7da67386cf
Update gradle.properties 2023-03-16 20:00:52 +06:00
InsanusMokrassar 7027719fe5
Update gradle-wrapper.properties 2023-03-16 20:00:20 +06:00
InsanusMokrassar a81c7c7c3f
Merge pull request #46 from Tolsi/patch-1
typo
2023-03-16 18:20:18 +06:00
Sergey Tolmachev e5658998d4
typo 2023-03-16 15:16:35 +03:00
InsanusMokrassar 6b3cb981ab
Merge pull request #45 from InsanusMokrassar/0.9.0
0.9.0
2023-02-28 12:48:51 +06:00
InsanusMokrassar f6518d4d25 add kotlin-js-store folder in gitignore 2023-02-28 12:25:23 +06:00
InsanusMokrassar 97a8f39826 update dependencies 2023-02-28 12:24:30 +06:00
InsanusMokrassar 469861f7e3 start 0.9.0 2023-02-28 12:23:12 +06:00
InsanusMokrassar 69305506ce
Update README.md 2023-02-19 16:35:31 +06:00
InsanusMokrassar 63ea3f0f1a
Merge pull request #44 from InsanusMokrassar/0.8.5
0.8.5
2022-12-15 08:38:54 +06:00
InsanusMokrassar 13a8bacb52 fix changelog 2022-12-15 08:37:54 +06:00
InsanusMokrassar 9c80e29e71 update autobuild script 2022-12-14 23:00:44 +06:00
InsanusMokrassar cfd2de8fe9 update dependencies 2022-12-14 22:45:34 +06:00
InsanusMokrassar e3490d432e fix in timezoned crontab scheduler 2022-12-14 22:44:27 +06:00
InsanusMokrassar 1c95636b71 start 0.8.5 2022-12-14 22:30:34 +06:00
InsanusMokrassar b31a6ab86a
Merge pull request #43 from InsanusMokrassar/0.8.4
0.8.4
2022-12-08 09:32:25 +06:00
57 changed files with 834 additions and 2327 deletions

View File

@ -10,10 +10,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 11
- name: Fix android 32.0.0 dx
continue-on-error: true
run: cd /usr/local/lib/android/sdk/build-tools/32.0.0/ && cp d8 dx && cd lib && cp d8.jar dx.jar
java-version: 17
- name: Build
run: ./gradlew dokkaHtml
- name: Publish KDocs

View File

@ -7,19 +7,21 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 11
- name: Fix android 32.0.0 dx
continue-on-error: true
run: cd /usr/local/lib/android/sdk/build-tools/32.0.0/ && cp d8 dx && cd lib && cp d8.jar dx.jar
java-version: 17
- name: Update version
run: |
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
sed -i -e "s/^version=\([0-9\.]*\)/version=\1-branch_$branch-build${{ github.run_number }}/" gradle.properties
- name: prebuild
run: ./gradlew clean build
- name: Publish to Gitea
continue-on-error: true
run: ./gradlew publishAllPublicationsToGiteaRepository
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
- name: Publish package
continue-on-error: true
run: ./gradlew --no-parallel publishAllPublicationsToGithubPackagesRepository -x signJsPublication -x signJvmPublication -x signKotlinMultiplatformPublication -x signAndroidReleasePublication -x signAndroidDebugPublication -x signAndroidReleasePublication
run: ./gradlew --no-parallel publishAllPublicationsToGithubPackagesRepository
env:
GITHUBPACKAGES_USER: ${{ github.actor }}
GITHUBPACKAGES_PASSWORD: ${{ secrets.GITHUB_TOKEN }}

2
.gitignore vendored
View File

@ -9,4 +9,6 @@ settings.xml
build/
out/
kotlin-js-store/
local.properties

View File

@ -1,5 +1,136 @@
# Changelog
## 2.3.0
* `doWhile` now will guarantee that it will not call `doOnce` more than once for time
## 2.2.9
* `Version`:
* `Kotlin`: `1.9.23`
* `Serialization`: `1.6.3`
* `Klock`: `5.3.2`
* Fixes in build-in schedulers
## 2.2.8
* `Version`:
* `Coroutines`: `1.8.0`
## 2.2.7
* `Version`:
* `Klock`: `5.3.1`
* `AndroidXWork`: `2.9.0`
## 2.2.6
**Since this version klock depdendency replaced with `com.soywiz.korge:korlibs-time`**
* `Version`:
* `Klock`: `5.3.0`
## 2.2.5
* `Versions`
* `Kotlin`: `1.9.22`
* `Serialization`: `1.6.2`
## 2.2.4
* `Versions`
* `Kotlin`: `1.9.21`
* `Serialization`: `1.6.1`
## 2.2.3
**THIS UPDATE CONTAINS UPGRADE OF USED JDK UP TO 17**
* Versions
* `Kotlin`: `1.9.20`
## 2.2.2
* Versions
* `Kotlin`: `1.9.20-RC`
* `Android` (min/target): `34`
## 2.2.1
* Potential fix of [#65](https://github.com/InsanusMokrassar/krontab/issues/65)
* Versions
* `Kotlin`: `1.9.20-Beta`
* `Klock`: `4.0.10`
* `Serialization`: `1.6.0`
## 2.2.0
* Versions
* `Kotlin`: `1.9.0`
* `Coroutines`: `1.7.3`
* `Klock`: `4.0.9`
## 2.1.2
* Versions
* `Coroutines`: `1.7.2`
* All callbacks for standard extensions like `doInfinity` now fully inline
## 2.1.1
* `asFlowWithoutDelays` and `asTzFlowWithoutDelays` will have nullable `since` parameters with default to `null`
to avoid any inconsistency of `Flow` idiom.
<details>
<summary>About the reason of changes</summary>
Cold flows should not contain some state by default. So, it was not right to save some `DateTime`/`DateTimeTz`
by default. Now it will not use some external state unless developers will set it manually
</details>
## 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
* `Kotlin`: `1.8.10`
* `AndroidXWork`: `2.8.0`
## 0.8.5
* Project is now available in owner `Gitea`: https://git.inmo.dev/InsanusMokrassar/-/packages/maven/dev.inmo-krontab
* `KronSchedulerTz#next` with incoming `DateTime` now will use adjusted local time instead of unadjusted one
* `CronDateTimeSchedulerTz#next` with incoming `DateTime` will convert that parameter to internal offset directly
## 0.8.4
* Versions

View File

@ -1,15 +1,17 @@
# krontab
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/krontab/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/krontab)
[![Build Status](https://github.com/InsanusMokrassar/krontab/actions/workflows/publishing_packages.yml/badge.svg)](https://github.com/InsanusMokrassar/krontab/actions/workflows/publishing_packages.yml)
![JVM](https://img.shields.io/badge/JVM-red?style=for-the-badge&logo=openjdk&logoColor=white)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/krontab/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/krontab)
[![Telegram Chat](https://img.shields.io/badge/Telegram%20Chat-0288D1?style=for-the-badge&logo=telegram&logoColor=white)](https://inmodev_chat.t.me)
![JVM](https://img.shields.io/badge/JVM-red?style=for-the-badge&logo=openjdk&logoColor=white)
![Android](https://img.shields.io/badge/Android-green?style=for-the-badge&logo=android&logoColor=white)
![Js](https://img.shields.io/badge/JavaScript-323330?style=for-the-badge&logo=javascript&logoColor=F7DF1E)
![Linux x64](https://img.shields.io/badge/Linux%20x64-white?style=for-the-badge&logo=linux&logoColor=black)
[![KDocs](https://img.shields.io/badge/KDocs-323330?style=for-the-badge&logo=Kotlin&logoColor=7F52FF)](https://insanusmokrassar.github.io/krontab/)
[![Tutorials](https://img.shields.io/badge/Tutorials-0288D1?style=for-the-badge&logo=bookstack&logoColor=white)](https://bookstack.inmo.dev/books/krontab)
[![Tutorials](https://img.shields.io/badge/Tutorials-0288D1?style=for-the-badge&logo=mkdocs&logoColor=white)](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.
@ -25,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
}

View File

@ -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,9 @@ kotlin {
android {
publishAllLibraryVariants()
}
linuxX64()
mingwX64()
linuxArm64()
sourceSets {
@ -64,8 +69,9 @@ 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"
api "com.soywiz.korge:korlibs-time:$klockVersion"
}
}
@ -79,6 +85,7 @@ kotlin {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlin_coroutines_version"
}
}
jvmTest {
@ -91,7 +98,7 @@ kotlin {
implementation kotlin('test-js')
}
}
androidTest {
androidUnitTest {
dependencies {
implementation kotlin('test-junit')
}
@ -102,8 +109,9 @@ kotlin {
apply plugin: 'com.getkeepsafe.dexcount'
android {
compileSdkVersion "$android_compileSdkVersion".toInteger()
buildToolsVersion "$android_buildToolsVersion"
compileSdk "$android_compileSdkVersion".toInteger()
buildToolsVersion = "$android_buildToolsVersion"
namespace "${group}.${project.name}"
defaultConfig {
minSdkVersion "$android_minSdkVersion".toInteger()
@ -121,8 +129,8 @@ android {
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
sourceSets {
@ -134,6 +142,6 @@ android {
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

View File

@ -18,13 +18,13 @@ if (new File(projectDir, "secret.gradle").exists()) {
githubRelease {
token "${project.property('GITHUB_RELEASE_TOKEN')}"
owner "InsanusMokrassar"
repo "${rootProject.name}"
owner = "InsanusMokrassar"
repo = "${rootProject.name}"
tagName "v${project.version}"
releaseName "${project.version}"
targetCommitish "${project.version}"
tagName = "v${project.version}"
releaseName = "${project.version}"
targetCommitish = "${project.version}"
body getCurrentVersionChangelog("${project.version}")
body = getCurrentVersionChangelog("${project.version}")
}
}

View File

@ -1,3 +1,4 @@
org.gradle.jvmargs=-Xmx512m
kotlin.code.style=official
org.gradle.parallel=true
kotlin.js.generate.externals=true
@ -8,30 +9,32 @@ android.useAndroidX=true
android.enableJetifier=false
kotlin_version=1.7.22
kotlin_coroutines_version=1.6.4
kotlin_version=1.9.23
kotlin_coroutines_version=1.8.0
kotlin_serialization_version=1.6.3
dokka_version=1.7.20
dokka_version=1.9.20
klockVersion=3.4.0
klockVersion=5.4.0
## Github reease
github_release_plugin_version=2.4.1
github_release_plugin_version=2.5.2
## Android
android_gradle_version=8.1.4
android_minSdkVersion=21
android_compileSdkVersion=33
android_buildToolsVersion=33.0.0
dexcount_version=3.1.0
android_compileSdkVersion=34
android_buildToolsVersion=34.0.0
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.7.1
androidx_work_version=2.9.0
## Common
version=0.8.4
android_code_version=21
version=2.3.0
android_code_version=40

View File

@ -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.5.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/krontab/blob/master/LICENSE"}],"mavenConfig":{"name":"Krontab","description":"It is an analog of crontab util for Kotlin Coroutines","url":"https://github.com/InsanusMokrassar/krontab","vcsUrl":"https://github.com/InsanusMokrassar/krontab.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/krontab"},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}]}}

View File

@ -1,8 +1,7 @@
apply plugin: 'maven-publish'
apply plugin: 'signing'
task javadocsJar(type: Jar) {
classifier = 'javadoc'
archiveClassifier = 'javadoc'
}
publishing {
@ -43,27 +42,77 @@ publishing {
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/InsanusMokrassar/krontab")
credentials {
username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
}
}
}
if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) {
maven {
name = "InmoNexus"
url = uri("https://nexus.inmo.dev/repository/maven-releases/")
credentials {
username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER')
password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD')
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven {
name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
}
}
if (project.hasProperty("signing.gnupg.keyName")) {
apply plugin: 'signing'
signing {
useGpgCmd()
sign publishing.publications
}
task signAll {
tasks.withType(Sign).forEach {
dependsOn(it)
}
}
signing {
useGpgCmd()
sign publishing.publications
// Workaround to make android sign operations depend on signing tasks
project.getTasks().withType(AbstractPublishToMaven.class).configureEach {
def signingTasks = project.getTasks().withType(Sign.class)
mustRunAfter(signingTasks)
}
// Workaround to make test tasks use sign
project.getTasks().withType(Sign.class).configureEach { signTask ->
def withoutSign = (signTask.name.startsWith("sign") ? signTask.name.minus("sign") : signTask.name)
def pubName = withoutSign.endsWith("Publication") ? withoutSign.substring(0, withoutSign.length() - "Publication".length()) : withoutSign
// These tasks only exist for native targets, hence findByName() to avoid trying to find them for other targets
// Task ':linkDebugTest<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def debugTestTask = tasks.findByName("linkDebugTest$pubName")
if (debugTestTask != null) {
signTask.mustRunAfter(debugTestTask)
}
// Task ':compileTestKotlin<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def testTask = tasks.findByName("compileTestKotlin$pubName")
if (testTask != null) {
signTask.mustRunAfter(testTask)
}
}
}

1
publish.kpsb Normal file
View File

@ -0,0 +1 @@
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/krontab/blob/master/LICENSE"}],"mavenConfig":{"name":"Krontab","description":"It is an analog of crontab util for Kotlin Coroutines","url":"https://github.com/InsanusMokrassar/krontab","vcsUrl":"https://github.com/InsanusMokrassar/krontab.git","developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/krontab"},{"name":"InmoNexus","url":"https://nexus.inmo.dev/repository/maven-releases/"},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}}}

6
renovate.json Normal file
View File

@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}

View File

@ -2,7 +2,8 @@ package dev.inmo.krontab
import android.content.Context
import androidx.work.*
import com.soywiz.klock.DateTime
import korlibs.time.DateTime
import korlibs.time.millisecondsLong
import java.util.concurrent.TimeUnit
/**

View File

@ -1,7 +1,8 @@
package dev.inmo.krontab
import com.soywiz.klock.DateTime
import com.soywiz.klock.DateTimeTz
import korlibs.time.DateTime
import korlibs.time.DateTimeTz
import korlibs.time.millisecondsLong
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlin.coroutines.coroutineContext
@ -14,7 +15,7 @@ import kotlin.coroutines.coroutineContext
*
* 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 (DateTime) -> T): T {
suspend inline fun <T> KronScheduler.doOnce(block: (DateTime) -> T): T {
val time = nextOrNow().also {
delay((it - DateTime.now()).millisecondsLong)
}
@ -29,7 +30,7 @@ suspend inline fun <T> KronScheduler.doOnce(noinline block: suspend (DateTime) -
* WARNING!!! In case if [KronScheduler.next] of [this] instance will return null, [block] will be called immediately
*/
@Deprecated("Replaceable", ReplaceWith("doOnce", "dev.inmo.krontab.doOnce"))
suspend inline fun <T> KronScheduler.doOnceLocal(noinline block: suspend (DateTime) -> T): T = doOnce(block)
suspend inline fun <T> KronScheduler.doOnceLocal(block: (DateTime) -> T): T = doOnce(block)
/**
* Execute [block] once at the [KronScheduler.next] time and return result of [block] calculation.
@ -53,7 +54,7 @@ suspend inline fun <T> KronScheduler.doOnceTz(noinline block: suspend (DateTimeT
*/
suspend inline fun <T> doOnce(
scheduleConfig: String,
noinline block: suspend (DateTime) -> T
block: (DateTime) -> T
) = buildSchedule(scheduleConfig).doOnce(block)
/**
@ -69,24 +70,42 @@ suspend inline fun <T> doOnceTz(
/**
* Will execute [block] while it will return true as a result of its calculation
*/
suspend inline fun KronScheduler.doWhile(noinline block: suspend (DateTime) -> Boolean) {
suspend inline fun KronScheduler.doWhile(block: (DateTime) -> Boolean) {
var latest: DateTime? = null
do {
delay(1L)
} while (doOnce(block))
val result = doOnce {
if (latest != it) {
latest = it
block(it)
} else {
null
}
}
} while (result == null || result)
}
/**
* Will execute [block] while it will return true as a result of its calculation
*/
@Deprecated("Replaceable", ReplaceWith("doWhile", "dev.inmo.krontab.doWhile"))
suspend inline fun KronScheduler.doWhileLocal(noinline block: suspend (DateTime) -> Boolean) = doWhile(block)
suspend inline fun KronScheduler.doWhileLocal(block: (DateTime) -> Boolean) = doWhile(block)
/**
* Will execute [block] while it will return true as a result of its calculation
*/
suspend inline fun KronScheduler.doWhileTz(noinline block: suspend (DateTimeTz) -> Boolean) {
var latest: DateTimeTz? = null
do {
delay(1L)
} while (doOnceTz(block))
val result = doOnceTz {
if (latest != it) {
latest = it
block(it)
} else {
null
}
}
} while (result == null || result)
}
/**
@ -96,7 +115,7 @@ suspend inline fun KronScheduler.doWhileTz(noinline block: suspend (DateTimeTz)
*/
suspend inline fun doWhile(
scheduleConfig: String,
noinline block: suspend (DateTime) -> Boolean
block: (DateTime) -> Boolean
) = buildSchedule(scheduleConfig).doWhile(block)
/**
@ -107,7 +126,7 @@ suspend inline fun doWhile(
@Deprecated("Replaceable", ReplaceWith("doWhile", "dev.inmo.krontab.doWhile"))
suspend inline fun doWhileLocal(
scheduleConfig: String,
noinline block: suspend (DateTime) -> Boolean
block: (DateTime) -> Boolean
) = doWhile(scheduleConfig, block)
/**
@ -124,7 +143,7 @@ suspend inline fun doWhileTz(
/**
* Will execute [block] without any checking of result
*/
suspend inline fun KronScheduler.doInfinity(noinline block: suspend (DateTime) -> Unit) = doWhile {
suspend inline fun KronScheduler.doInfinity(block: (DateTime) -> Unit) = doWhile {
block(it)
coroutineContext.isActive
}
@ -132,7 +151,7 @@ suspend inline fun KronScheduler.doInfinity(noinline block: suspend (DateTime) -
* Will execute [block] without any checking of result
*/
@Deprecated("Replaceable", ReplaceWith("doInfinity", "dev.inmo.krontab.doInfinity"))
suspend inline fun KronScheduler.doInfinityLocal(noinline block: suspend (DateTime) -> Unit) = doInfinity(block)
suspend inline fun KronScheduler.doInfinityLocal(block: (DateTime) -> Unit) = doInfinity(block)
/**
* Will execute [block] without any checking of result
@ -149,7 +168,7 @@ suspend inline fun KronScheduler.doInfinityTz(noinline block: suspend (DateTimeT
*/
suspend inline fun doInfinity(
scheduleConfig: String,
noinline block: suspend (DateTime) -> Unit
block: (DateTime) -> Unit
) = buildSchedule(scheduleConfig).doInfinity(block)
/**
@ -160,7 +179,7 @@ suspend inline fun doInfinity(
@Deprecated("Replaceable", ReplaceWith("doInfinity", "dev.inmo.krontab.doInfinity"))
suspend inline fun doInfinityLocal(
scheduleConfig: String,
noinline block: suspend (DateTime) -> Unit
block: (DateTime) -> Unit
) = doInfinity(scheduleConfig, block)
/**

View File

@ -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)

View File

@ -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
@ -13,7 +13,7 @@ import com.soywiz.klock.DateTimeTz
interface KronSchedulerTz : KronScheduler {
suspend fun next(relatively: DateTimeTz): DateTimeTz?
override suspend fun next(relatively: DateTime): DateTime? = next(relatively.localUnadjusted) ?.local
override suspend fun next(relatively: DateTime): DateTime? = next(relatively.local) ?.local
}
suspend fun KronSchedulerTz.nextOrRelative(relatively: DateTimeTz): DateTimeTz = next(relatively) ?: getAnyNext(
@ -31,4 +31,4 @@ suspend fun KronScheduler.next(relatively: DateTimeTz) = if (this is KronSchedul
this.next(relatively.local) ?.toOffsetUnadjusted(relatively.offset)
}
suspend fun KronScheduler.nextTimeZoned() = next(DateTime.now().local)
suspend fun KronScheduler.nextTimeZoned() = next(DateTime.now().local)

View 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}
* * *&#47;{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)
)
}
}
}

View File

@ -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)

View File

@ -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?

View File

@ -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?

View File

@ -0,0 +1,133 @@
package dev.inmo.krontab
import korlibs.time.DateTime
import dev.inmo.krontab.builder.buildSchedule
import dev.inmo.krontab.internal.*
internal val anyCronDateTime by lazy {
CronDateTime()
}
internal fun getAnyNext(relatively: DateTime) = anyCronDateTime.toNearDateTime(relatively)!!
/**
* [KronScheduler.next] will always return [korlibs.time.DateTime.now]
*/
val AnyTimeScheduler: KronScheduler by lazy {
CronDateTimeScheduler(anyCronDateTime)
}
/**
* [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 [korlibs.time.DateTime.now] + one second
*/
val EverySecondScheduler: KronScheduler by lazy {
buildSchedule { seconds { 0 every 1 } }
}
/**
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one minute
*/
val EveryMinuteScheduler: KronScheduler by lazy {
buildSchedule {
seconds { at(0) }
minutes { 0 every 1 }
}
}
/**
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one hour
*/
val EveryHourScheduler: KronScheduler by lazy {
buildSchedule {
seconds { at(0) }
minutes { at(0) }
hours { 0 every 1 }
}
}
/**
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one day
*/
val EveryDayOfMonthScheduler: KronScheduler by lazy {
buildSchedule {
seconds { at(0) }
minutes { at(0) }
hours { at(0) }
dayOfMonth { 0 every 1 }
}
}
/**
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one month
*/
val EveryMonthScheduler: KronScheduler by lazy {
buildSchedule {
seconds { at(0) }
minutes { at(0) }
hours { at(0) }
dayOfMonth { at(0) }
months { 0 every 1 }
}
}
/**
* [KronScheduler.next] will always return [korlibs.time.DateTime.now] + one year
*/
val EveryYearScheduler: KronScheduler by lazy {
buildSchedule {
seconds { at(0) }
minutes { at(0) }
hours { at(0) }
dayOfMonth { at(0) }
months { at(0) }
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

View File

@ -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]

View File

@ -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,
@ -161,15 +182,24 @@ class SchedulerBuilder(
*/
fun build(): KronScheduler = offset ?.let {
createKronSchedulerWithOffset(
seconds,
minutes,
hours,
dayOfMonth,
month,
year,
dayOfWeek,
TimezoneOffset(it.minutes),
milliseconds ?: millisecondsArrayDefault
seconds = seconds,
minutes = minutes,
hours = hours,
dayOfMonth = dayOfMonth,
month = month,
years = year,
weekDays = dayOfWeek,
offset = TimezoneOffset(it.minutes),
milliseconds = milliseconds ?: millisecondsArrayDefault
)
} ?: createKronScheduler(seconds, minutes, hours, dayOfMonth, month, year, dayOfWeek, milliseconds ?: millisecondsArrayDefault)
} ?: createKronScheduler(
seconds = seconds,
minutes = minutes,
hours = hours,
dayOfMonth = dayOfMonth,
month = month,
years = year,
weekDays = dayOfWeek,
milliseconds = milliseconds ?: millisecondsArrayDefault
)
}

View File

@ -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.*

View File

@ -1,66 +0,0 @@
package dev.inmo.krontab
import com.soywiz.klock.DateTime
import dev.inmo.krontab.builder.buildSchedule
import dev.inmo.krontab.internal.*
internal val anyCronDateTime by lazy {
CronDateTime()
}
internal fun getAnyNext(relatively: DateTime) = anyCronDateTime.toNearDateTime(relatively)!!
/**
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now]
*/
val AnyTimeScheduler: KronScheduler by lazy {
CronDateTimeScheduler(anyCronDateTime)
}
/**
* [KronScheduler.next] will always return [com.soywiz.klock.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
*/
val EverySecondScheduler: KronScheduler by lazy {
buildSchedule { seconds { 0 every 1 } }
}
/**
* [KronScheduler.next] will always return [com.soywiz.klock.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
*/
val EveryHourScheduler: KronScheduler by lazy {
buildSchedule { hours { 0 every 1 } }
}
/**
* [KronScheduler.next] will always return [com.soywiz.klock.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
*/
val EveryMonthScheduler: KronScheduler by lazy {
buildSchedule { months { 0 every 1 } }
}
/**
* [KronScheduler.next] will always return [com.soywiz.klock.DateTime.now] + one year
*/
val EveryYearScheduler: KronScheduler by lazy {
buildSchedule { years { 0 every 1 } }
}

View File

@ -1,36 +0,0 @@
package dev.inmo.krontab.utils
import com.soywiz.klock.DateTime
import com.soywiz.klock.DateTimeTz
import dev.inmo.krontab.*
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.isActive
/**
* This [Flow] will trigger emitting each near time which will be returned from [this] [KronScheduler] with attention to
* time zones
*
* @see channelFlow
* @see KronSchedulerTz.doInfinityTz
*/
@FlowPreview
fun KronScheduler.asTzFlow(): Flow<DateTimeTz> = channelFlow {
doInfinityTz {
send(it)
}
}
/**
* This method is a map for [asTzFlow] and will works the same but return flow with [DateTime]s
*
* @see channelFlow
* @see KronScheduler.doInfinity
*/
@FlowPreview
fun KronScheduler.asFlow(): Flow<DateTime> = channelFlow {
doInfinity {
send(it)
}
}

View File

@ -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
/**

View File

@ -1,6 +1,6 @@
package dev.inmo.krontab.internal
import com.soywiz.klock.DateTime
import korlibs.time.DateTime
import dev.inmo.krontab.KronScheduler
/**

View File

@ -1,7 +1,8 @@
package dev.inmo.krontab.internal
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
@ -18,6 +19,10 @@ internal data class CronDateTimeSchedulerTz internal constructor(
val dateTimeWithActualOffset = relatively.toOffset(offset).local
return cronDateTime.toNearDateTime(dateTimeWithActualOffset) ?.toOffsetUnadjusted(offset) ?.toOffset(relatively.offset)
}
override suspend fun next(relatively: DateTime): DateTime? {
return next(relatively.toOffset(offset)) ?.utc
}
}
internal fun mergeCronDateTimeSchedulers(

View File

@ -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
@ -108,13 +108,19 @@ internal fun NearDateTimeCalculatorDays(
} else {
dateTime
})
dateTime.copy(
val newDateTime = dateTime.copy(
dayOfMonth = min(dateTime.month.days(dateTime.year), newOne.toInt() + 1), // index1
hour = 0,
minute = 0,
second = 0,
milliseconds = 0
)
// If day of month has not been changed, use old dateTime due to no changes required
if (newDateTime.dayOfMonth == dateTime.dayOfMonth) {
dateTime
} else {
newDateTime
}
}
)

View File

@ -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(

View File

@ -0,0 +1,94 @@
package dev.inmo.krontab.utils
import korlibs.time.DateTime
import korlibs.time.DateTimeTz
import korlibs.time.milliseconds
import dev.inmo.krontab.KronScheduler
import dev.inmo.krontab.next
import korlibs.time.millisecondsLong
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.isActive
/**
* **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. If passed null, `flow`
* will always start since the moment of collecting start
*/
fun KronScheduler.asTzFlowWithoutDelays(since: DateTimeTz? = null): Flow<DateTimeTz> = flow {
var previous = since ?: DateTime.nowLocal()
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 [asTzFlowWithoutDelays], but stop on each time until this time will happen
*/
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. If passed null, `flow`
* will always start since the moment of collecting start
*/
fun KronScheduler.asFlowWithoutDelays(since: DateTime? = null): Flow<DateTime> = flow {
var previous = since ?: DateTime.now()
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()

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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")

View File

@ -0,0 +1,38 @@
package dev.inmo.krontab.utils
import dev.inmo.krontab.*
import korlibs.time.*
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
class BuildersTest {
@Test
fun presetsWorksCorrectly() {
val data = mapOf(
EverySecondScheduler to { it: DateTime -> if (it.milliseconds > 0 ) it + 1.seconds - it.milliseconds.milliseconds else it },
EveryMinuteScheduler to { it: DateTime -> if (it.seconds > 0 || it.milliseconds > 0 ) it + 1.minutes - it.seconds.seconds - it.milliseconds.milliseconds else it },
EveryHourScheduler to { it: DateTime -> if (it.minutes > 0 || it.seconds > 0 || it.milliseconds > 0 ) it + 1.hours - it.minutes.minutes - it.seconds.seconds - it.milliseconds.milliseconds else it },
EveryDayOfMonthScheduler to { it: DateTime -> if (it.hours > 0 || it.minutes > 0 || it.seconds > 0 || it.milliseconds > 0 ) it + 1.days - it.hours.hours - it.minutes.minutes - it.seconds.seconds - it.milliseconds.milliseconds else it },
EveryMonthScheduler to { it: DateTime -> if (it.dayOfMonth > 1 || it.hours > 0 || it.minutes > 0 || it.seconds > 0 || it.milliseconds > 0 ) (it + 1.months).copy(dayOfMonth = 1, hour = 0, minute = 0, second = 0, milliseconds = 0) else it },
)
val samples = 10000
runTest {
var now = DateTime.now()
for (i in 0 until samples) {
data.forEach { (scheduler, expectCalculator) ->
val expectValue = expectCalculator(now)
val newNow = scheduler.nextOrRelative(now)
assertEquals(expectValue, newNow, "For time ${now.toStringDefault()} calculated wrong value: ${newNow.toStringDefault()} is not equal to ${expectValue.toStringDefault()}")
now = newNow
}
}
}
}
}

View File

@ -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 {

View File

@ -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)

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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.*

View File

@ -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)

View File

@ -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) }

View File

@ -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)

View File

@ -1 +0,0 @@
<manifest package="dev.inmo.krontab"/>