From 3f132da62d520e46e6a9fa0b049b95fdebc37f9e Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Sat, 2 Jan 2021 23:56:31 +0600 Subject: [PATCH] add KronSchedulerWork --- CHANGELOG.md | 2 +- .../dev/inmo/krontab/KronSchedulerWork.kt | 94 +++++++++++++++++++ .../inmo/krontab/KronSchedulerWorkRequest.kt | 18 ---- 3 files changed, 95 insertions(+), 19 deletions(-) create mode 100644 src/main/kotlin/dev/inmo/krontab/KronSchedulerWork.kt delete mode 100644 src/main/kotlin/dev/inmo/krontab/KronSchedulerWorkRequest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index f446586..9bda26c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ * `KrontabTemplateWrapper` has been added * New extension `KrontabTemplate#toKronScheduler` (works as `toSchedule`) * **Fixed issue related to the fact that `toNearDateTime` of `CronDateTime` incorrectly handled months - +* **Android target has been added** ## 0.4.2 diff --git a/src/main/kotlin/dev/inmo/krontab/KronSchedulerWork.kt b/src/main/kotlin/dev/inmo/krontab/KronSchedulerWork.kt new file mode 100644 index 0000000..c770cc3 --- /dev/null +++ b/src/main/kotlin/dev/inmo/krontab/KronSchedulerWork.kt @@ -0,0 +1,94 @@ +package dev.inmo.krontab + +import android.content.Context +import androidx.work.* +import com.soywiz.klock.DateTime +import java.util.concurrent.TimeUnit + +suspend fun Context.enqueueKronSchedulerWork( + workName: String, + delayMillis: Long, + workClass: Class, + setUpRequest: suspend OneTimeWorkRequest.Builder.() -> Unit +) = WorkManager.getInstance(applicationContext).enqueueUniqueWork( + workName, + ExistingWorkPolicy.REPLACE, + OneTimeWorkRequest.Builder(workClass).apply { + setInitialDelay(delayMillis, TimeUnit.MILLISECONDS) + setUpRequest() + }.build() +) +suspend inline fun Context.enqueueKronSchedulerWork( + workName: String, + delayMillis: Long, + noinline setUpRequest: suspend OneTimeWorkRequest.Builder.() -> Unit +) = enqueueKronSchedulerWork(workName, delayMillis, T::class.java, setUpRequest) + +suspend fun Context.enqueueKronSchedulerWork( + workName: String, + initialScheduler: KronScheduler, + workClass: Class, + setUpRequest: suspend OneTimeWorkRequest.Builder.() -> Unit +): Operation? { + val now = DateTime.now() + val nextTriggerTime = initialScheduler.next(now) + val delayMillis = nextTriggerTime ?.minus(now) ?.millisecondsLong ?: return null + + return enqueueKronSchedulerWork(workName, delayMillis, workClass, setUpRequest) +} +suspend inline fun Context.enqueueKronSchedulerWork( + workName: String, + initialScheduler: KronScheduler, + noinline setUpRequest: suspend OneTimeWorkRequest.Builder.() -> Unit +) = enqueueKronSchedulerWork(workName, initialScheduler, T::class.java, setUpRequest) + +/** + * Use this class as an super class in case you wish to implement krontab-based enqueuing of works + */ +abstract class KronSchedulerWork( + context: Context, + workerParams: WorkerParameters +) : CoroutineWorker( + context, + workerParams +) { + protected abstract val workName: String + protected open val prolongWork: Boolean = true + protected open val prolongOnFailure + get() = prolongWork + protected open val prolongOnException = false + protected open val prolongOnNextAbsent = false + + protected abstract suspend fun kronScheduler(): KronScheduler? + protected abstract suspend fun onWork(): Result + protected open suspend fun OneTimeWorkRequest.Builder.setUpRequest() {} + + protected suspend fun prolong() { + val now = DateTime.now() + val nextTriggerTime = kronScheduler() ?.let { + if (prolongOnNextAbsent) { + it.nextOrRelative(now) + } else { + it.next(now) + } + } + val delayMillis = nextTriggerTime ?.minus(now) ?.millisecondsLong ?: return + + applicationContext.enqueueKronSchedulerWork(workName, delayMillis, this::class.java) { setUpRequest() } + } + + override suspend fun doWork(): Result { + val result = try { + onWork() + } catch (e: Throwable) { + if (prolongOnException) { + prolong() + } + throw e + } + if (result !is Result.Failure || prolongOnFailure) { + prolong() + } + return result + } +} diff --git a/src/main/kotlin/dev/inmo/krontab/KronSchedulerWorkRequest.kt b/src/main/kotlin/dev/inmo/krontab/KronSchedulerWorkRequest.kt deleted file mode 100644 index 534f820..0000000 --- a/src/main/kotlin/dev/inmo/krontab/KronSchedulerWorkRequest.kt +++ /dev/null @@ -1,18 +0,0 @@ -package dev.inmo.krontab - -import android.content.Context -import androidx.work.* - -//fun KronScheduler.workRequest(context: Context) = OneTimeWorkRequestBuilder<>() -// -//abstract class KronSchedulerWorkRequest( -// context: Context, -// workerParams: WorkerParameters -//) : CoroutineWorker( -// context, -// workerParams -//) { -// override suspend fun doWork(): Result { -// -// } -//}