Lorraine is a lightweight, persistent work management framework for Kotlin Multiplatform. Inspired by Android's WorkManager and NSOperation, it provides a unified API for managing background tasks across Android and iOS, ensuring they run even if the app is restarted.
- 📱 Kotlin Multiplatform: Shared logic for Android and iOS.
- 💾 Persistence: Tasks are stored in a local SQLite database (via Room) and resumed after app restarts.
- 🔗 Work Chaining: Easily chain multiple tasks together with
thenoperations. - ⚙️ Constraints: Define requirements like
requiredNetworkandrequireBatteryNotLowfor your tasks. - 🛠️ DSL-based API: Clean and intuitive DSL for initialization and task definition.
- 📊 Monitoring: Observe task status using Kotlin Flows.
Add the dependency to your project using Version Catalogs:
[versions]
lorraine = "0.3.0" # Use the latest version
[libraries]
lorraine = { module = "io.github.dottttt.lorraine:lorraine", version.ref = "lorraine" }In your module's build.gradle.kts:
kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.lorraine)
}
}
}Create your background logic by extending WorkLorraine. Use LorraineResult to communicate the outcome.
class SyncDataWorker : WorkLorraine() {
override suspend fun doWork(inputData: LorraineData?): LorraineResult {
return try {
// Your heavy work here
// val userId = inputData?.getString("userId")
LorraineResult.success()
} catch (e: Exception) {
LorraineResult.retry() // Or LorraineResult.failure()
}
}
}Register your workers during app startup.
const val SYNC_USER = "SYNC_USER"
fun initLorraine(context: LorraineContext): Lorraine {
return startLorraine(context) {
work(SYNC_USER) { SyncDataWorker() }
logger {
enable = true // Enable internal logging for debugging
}
}
}class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
initLorraine(createLorraineContext(this))
}
}// In your iOS Application delegate or SwiftUI App
initLorraine(createLorraineContext())lorraine.enqueue(
queueId = "single_sync",
type = ExistingLorrainePolicy.REPLACE,
request = lorraineRequest {
identifier = SYNC_USER
constraints {
requiredNetwork = true
}
}
)Combine multiple requests into a single operation.
val operation = lorraineOperation {
existingPolicy = ExistingLorrainePolicy.APPEND
startWith {
identifier = "REFRESH_TOKEN"
}
then {
identifier = SYNC_USER
}
}
lorraine.enqueue("user_refresh_chain", operation)You can monitor the status of your tasks in real-time:
lorraine.listenLorrainesInfo().collect { infoList ->
infoList.forEach { info ->
println("Task ${info.id}: ${info.state}")
}
}-
Add support for
PeriodicWork - JVM Support
- WASM Support
- Advanced iOS BackgroundTask integration
Contributions are welcome! Please feel free to open a pull request or report issues.
- Koin - For the elegant DSL structure.
- WorkManager - For the core concepts of persistent background work.
- NSOperation - For task queueing logic.