Skip to content
This repository has been archived by the owner on Oct 14, 2023. It is now read-only.

Commit

Permalink
Merge pull request #4 from Liftric/feat/serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
gaebel authored Jan 13, 2023
2 parents f9de439 + fc0d1af commit f2ad415
Show file tree
Hide file tree
Showing 46 changed files with 787 additions and 651 deletions.
11 changes: 5 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
name: Build & test

on:
pull_request:
types: [ opened, reopened, synchronize ]
Expand All @@ -8,19 +7,19 @@ on:
push:
branches:
- main

jobs:
test:
runs-on: macOS-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: set up JDK 11
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: 11
java-version: '11'
distribution: 'adopt'
- name: Build and test
run: region=${{ secrets.region }} clientId=${{ secrets.clientid }} ./gradlew build test
run: ./gradlew build test
- name: Upload test result
if: ${{ always() }}
uses: actions/upload-artifact@v2
Expand Down
25 changes: 12 additions & 13 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
name: Publish to OSSRH
name: Publish to Github
on:
release:
types: [published]

jobs:
publish:
runs-on: macOS-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: 11
java-version: '11'
distribution: 'adopt'
- name: Validate Gradle wrapper
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b
- name: Grant Permission to Execute
run: chmod +x gradlew
- name: New version
run: ./gradlew versionDisplay
- name: Publish Library
- name: Publish package
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: publish
env:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME }}
ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD }}
ORG_GRADLE_PROJECT_npmAccessKey: ${{ secrets.NPMJS_ACCESS_KEY }}
run: region=${{ secrets.region }} clientId=${{ secrets.clientid }} ./gradlew publishAllPublicationsToSonatypeRepository
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43 changes: 29 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Persisted-queue
# kmm-job-queue

Coroutine job scheduler inspired by `Android Work Manager` and `android-priority-jobqueue` for Kotlin Multiplatform projects. Run & repeat tasks. Rebuild them from disk. Fine tune execution with rules.
Coroutine job scheduler for Kotlin Multiplatform projects. Run & repeat tasks. Rebuild them from disk. Fine tune execution with rules.

The library depends on `kotlinx-serialization` for the persistence of the jobs.

⚠️ The project is still work in progress and shouldn't be used in a production project.

## Rules

Expand All @@ -9,15 +13,17 @@ Coroutine job scheduler inspired by `Android Work Manager` and `android-priority
- [x] Retry
- [x] Periodic
- [x] Unique
- [ ] Internet
- [ ] Network

## Capabilities

- [x] Cancellation (all, by id, by tag)
- [x] Cancellation (all, by id)
- [x] Start & stop scheduling
- [x] Restore from disk (after start)

## Example

Define a `DataTask<*>` or a `Task` (`DataTask<Unit>`), customize its body and limit when it should repeat.
Define a `Task` (or `DataTask<T>`), customize its body and limit when it should repeat.

⚠️ Make sure the data you pass into the task is serializable.

Expand All @@ -27,25 +33,31 @@ data class UploadData(val id: String)

class UploadTask(data: UploadData): DataTask<UploadData>(data) {
override suspend fun body() { /* Do something */ }
override suspend fun onRepeat(cause: Throwable): Boolean { cause is NetworkException }
override suspend fun onRepeat(cause: Throwable): Boolean { cause is NetworkException } // Won't retry if false
}
```

Create a single instance of the scheduler on app start. To start enqueuing jobs run `queue.start()`.
Create a single instance of the job queue on app start. To start enqueuing jobs run `jobQueue.start()`.

⚠️ You have to provide the polymorphic serializer of your custom task **if you want to persist it**.

You can pass a `Queue.Configuration` or a custom `JobSerializer` to the scheduler.
You can pass a custom `Queue.Configuration` or `JsonStorage` to the job queue.

```kotlin
val scheduler = JobScheduler()
scheduler.queue.start()
val jobQueue = JobQueue(serializers = SerializersModule {
polymorphic(Task::class) {
subclass(UploadTask::class, UploadTask.serializer())
}
})
jobQueue.start()
```

You can customize the jobs life cycle during schedule by defining rules.

```kotlin
val data = UploadData(id = ...)
val data = UploadData(id = "123456")

scheduler.schedule(UploadTask(data)) {
jobQueue.schedule(UploadTask(data)) {
unique(data.id)
retry(RetryLimit.Limited(3), delay = 30.seconds)
persist()
Expand All @@ -55,7 +67,10 @@ scheduler.schedule(UploadTask(data)) {
You can subscribe to life cycle events (e.g. for logging).

```kotlin
scheduler.onEvent.collect { event ->
Logger.info(event)
jobQueue.listener.collect { event ->
when (event) {
is JobEvent.DidFail -> Logger.error(event.error)
else -> Logger.info(event)
}
}
```
76 changes: 43 additions & 33 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.gradle.targets.native.tasks.KotlinNativeSimulatorTest

plugins {
id("com.android.library") version libs.versions.android.tools.gradle
kotlin("multiplatform") version libs.versions.kotlin
Expand All @@ -7,22 +9,13 @@ plugins {
id("signing")
}

repositories {
mavenCentral()
google()
gradlePluginPortal()
}

java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
group = "com.liftric"
version = with(versioning.info) {
if (branch == "HEAD" && dirty.not()) tag else full
}

kotlin {
ios {
binaries.framework()
}

ios()
iosSimulatorArm64()

android {
Expand All @@ -44,6 +37,8 @@ kotlin {
implementation(kotlin("test"))
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation(libs.multiplatform.settings.test)
implementation(libs.kotlinx.coroutines.test)
}
}
val androidMain by getting
Expand All @@ -53,6 +48,9 @@ kotlin {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
implementation(libs.androidx.test.core)
implementation(libs.androidx.test.runner)
implementation(libs.androidx.test.ext)

}
}
val iosMain by getting
Expand All @@ -73,34 +71,40 @@ kotlin {
}

android {
compileSdk = 30
compileSdk = 33

namespace = "com.liftric.job.queue"

defaultConfig {
minSdk = 21
targetSdk = 30
targetSdk = 33
testInstrumentationRunner = "androidx.test.runner"
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

testOptions {
unitTests.apply {
unitTests {
isReturnDefaultValues = true
}
}
publishing {
multipleVariants {
withSourcesJar()
withJavadocJar()
allVariants()
}
}
}

group = "com.liftric"
version = with(versioning.info) {
if (branch == "HEAD" && dirty.not()) tag else full
}

afterEvaluate {
project.publishing.publications.withType(MavenPublication::class.java).forEach {
it.groupId = group.toString()
tasks {
withType<KotlinNativeSimulatorTest> {
deviceId = "iPhone 14"
}
withType(JavaCompile::class) {
options.release.set(11)
}
}

Expand All @@ -114,11 +118,11 @@ val javadocJar by tasks.registering(Jar::class) {
publishing {
repositories {
maven {
name = "sonatype"
setUrl("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
name = "GitHubPackages"
setUrl("https://maven.pkg.github.com/Liftric/kmm-job-queue")
credentials {
username = ossrhUsername
password = ossrhPassword
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
Expand All @@ -128,13 +132,13 @@ publishing {

pom {
name.set(project.name)
description.set("Kotlin Multiplatform persisted queue library.")
url.set("https://github.com/liftric/cognito-idp")
description.set("Persistable coroutine job queue for Kotlin Multiplatform projects.")
url.set("https://github.com/Liftric/kmm-job-queue")

licenses {
license {
name.set("MIT")
url.set("https://github.com/liftric/cognito-idp/blob/master/LICENSE")
url.set("https://github.com/Liftric/kmm-job-queue/blob/master/LICENSE")
}
}
developers {
Expand All @@ -145,12 +149,18 @@ publishing {
}
}
scm {
url.set("https://github.com/liftric/persisted-queue")
url.set("https://github.com/Liftric/kmm-job-queue")
}
}
}
}

afterEvaluate {
project.publishing.publications.withType(MavenPublication::class.java).forEach {
it.groupId = group.toString()
}
}

signing {
val signingKey: String? by project
val signingPassword: String? by project
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
android.useAndroidX=true
android.disableAutomaticComponentCreation=true
org.gradle.parallel=true
org.gradle.jvmargs=-Xmx4096m
org.gradle.vfs.watch=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.mpp.enableCompatibilityMetadataVariant=true
kotlin.mpp.androidSourceSetLayoutVersion1.nowarn=true
kotlin.incremental=true
kotlin.incremental.multiplatform=true
kotlin.caching.enabled=true
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
14 changes: 9 additions & 5 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
rootProject.name = "persisted-queue"
rootProject.name = "job-queue"

pluginManagement {
repositories {
Expand All @@ -16,15 +16,19 @@ dependencyResolutionManagement {

versionCatalogs {
create("libs") {
version("android-tools-gradle", "7.2.2")
version("kotlin", "1.7.20")
version("android-tools-gradle", "7.3.0")
version("kotlin", "1.8.0")
library("kotlinx-coroutines", "org.jetbrains.kotlinx", "kotlinx-coroutines-core").version("1.6.4")
library("kotlinx-serialization", "org.jetbrains.kotlinx", "kotlinx-serialization-json").version("1.4.0")
library("kotlinx-atomicfu", "org.jetbrains.kotlinx", "atomicfu").version("0.18.5")
library("kotlinx-coroutines-test", "org.jetbrains.kotlinx", "kotlinx-coroutines-test").version("1.6.4")
library("kotlinx-serialization", "org.jetbrains.kotlinx", "kotlinx-serialization-json").version("1.4.1")
library("kotlinx-atomicfu", "org.jetbrains.kotlinx", "atomicfu").version("0.19.0")
library("kotlinx-datetime", "org.jetbrains.kotlinx", "kotlinx-datetime").version("0.4.0")
library("androidx-test-core", "androidx.test", "core").version("1.4.0")
library("androidx-test-runner", "androidx.test", "runner").version("1.4.0")
library("androidx-test-ext", "androidx.test.ext", "junit").version("1.1.3")
library("roboelectric", "org.robolectric", "robolectric").version("4.5.1")
library("multiplatform-settings", "com.russhwolf", "multiplatform-settings").version("1.0.0-RC")
library("multiplatform-settings-test", "com.russhwolf", "multiplatform-settings-test").version("1.0.0-RC")
plugin("versioning", "net.nemerosa.versioning").version("3.0.0")
plugin("kotlin.serialization", "org.jetbrains.kotlin.plugin.serialization").versionRef("kotlin")
}
Expand Down
16 changes: 16 additions & 0 deletions src/androidMain/kotlin/com/liftric/job/queue/JobQueue.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.liftric.job.queue

import android.content.Context
import com.russhwolf.settings.SharedPreferencesSettings
import kotlinx.serialization.modules.SerializersModule

actual class JobQueue(
context: Context,
serializers: SerializersModule = SerializersModule {},
configuration: Queue.Configuration = Queue.DefaultConfiguration,
store: JsonStorage = SettingsStorage(SharedPreferencesSettings.Factory(context).create("com.liftric.persisted.queue"))
) : AbstractJobQueue(
serializers,
configuration,
store
)
Loading

0 comments on commit f2ad415

Please sign in to comment.