Skip to content

Migrate ensureBackgroundThread to coroutines for concurrency management #872

Description

@kvithayathil

Checklist

  • I made sure that there are no existing issues - open or closed - to which I could contribute my information.
  • I made sure that there are no existing discussions - open or closed - to which I could contribute my information.
  • I have read the FAQs inside the app (Menu -> About -> FAQs), in the README and my problem isn't listed.
  • I have taken the time to fill in all the required details. I understand that the request may get dismissed otherwise.
  • This issue contains only one feature request.

Which apps should have this feature?

All Fossify Apps

Feature description

Refactor the internal implementation of ensureBackgroundThread with a coroutine-based approach while preserving the exact same function signature. This requires no updates from callers

The approach I propose is as follows:

1 - Add the coroutines bill of materials 'bom' dependency to libs.versions.toml. We also declare the specific coroutines libraries we want:

# commons/gradle/libs.versions.toml
[versions]
coroutines = "1.9.0"

[libraries]
kotlinx-coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version.ref = "coroutines" }
# BOM libraries we want to use (no versioning needed)
kotlinx-coroutines-test = { "org.jetbrains.kotlinx:kotlinx-coroutines-test" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android" }  

2 - Declare the coroutine dependencies in the commons project build.gradle.kts

// commons/build.gradle.kts
dependencies {
    // ... existing dependencies ...
    api(platform(libs.kotlinx.coroutines.bom)) // platform wrapper needed for automated version alignment
    api(libs.kotlinx.coroutines.android)
    testImplementation(libs.kotlinx.coroutines.test)
}

3 - Create a dedicated org.fossify.commons.concurrency package and add the following:

DispatcherProviders.kt which contains the coroutine dispatchers. This interface wrapper helps with testability as the callers aren't tightly coupled to a hard-coded dispatcher implementation

// commons/.../concurrency/DispatchersProvider.kt

interface DispatchersProvider {
    fun io(): CoroutineDispatcher = Dispatchers.IO
    fun main(): CoroutineDispatcher = Dispatchers.Main.immediate
    fun default(): CoroutineDispatcher = Dispatchers.Default
}

// For run time. We can make a different implementation for testing while keeping the same calling interface

object DefaultDispatcherProvider : DispatcherProvider {
    override val main: CoroutineDispatcher = Dispatchers.Main
    override val io: CoroutineDispatcher = Dispatchers.IO
    override val default: CoroutineDispatcher = Dispatchers.Default
    override val unconfined: CoroutineDispatcher = Dispatchers.Unconfined
}

4 - Then we refactor ensureBackgroundThread to be the following:

// commons/.../helpers/Constants.kt (existing location — no import breakage)

// Provides a container for structured concurrency
private val backgroundScope = CoroutineScope(
    SupervisorJob()
        + AppDispatchers.provider.io()
        + CoroutineExceptionHandler { _, throwable ->
            Log.e("BackgroundScope", "Uncaught exception in background work", throwable)
        }
)

fun ensureBackgroundThread(callback: () -> Unit) {
    backgroundScope.launch {
        callback()
    }
}

The existing function signature is retained which means no changes needed to ensureBackgroundThread.

We get a good foundation for any future concurrency enhancements in future.

Why do you want this feature?

Additional information

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssue is about a new feature or improving existing feature/behavior.needs triageIssue is not yet ready for PR authors to take up

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions