[SOLVED] Kotlin + Arrow-kt – why are my coroutines not cancelling properly?

Issue

This Content is from Stack Overflow. Question asked by LeYAUable

I am using Kotlin together with Arrow-Kt libraries.
I am launching on a specific scope some coroutines that make use of Arrow-kt’s Schedule.

At a certain time, I want to be able to cancel all those coroutines that were launched on that scope, but after I cancel the scope basically nothing changes and whatever was running on the Schedule, continues to run, which is not what I wanted.

I already tried to place some yield() calls to force the coroutines to be cancellable, but the behavior didn’t change.

Here is the code:

Main function doing the launches:

    private val ballFetchingScope= CoroutineScope(CoroutineName("ball-fetching"))
    fun fetchBalls(periodicity: Periodicity) {
        val balls = stockRepository.getAllBalls() //basically a list of different balls

        balls.forEach {
                ballFetchingScope.launch(Dispatchers.IO) { ballFetcher.startFetching(it, periodicity) }
        }
    }

startFetching function, using Arrow-kt’s schedule:

    suspend fun startFetching(ball: Ball, periodicity: Periodicity) {

        Schedule.forever<Unit>()
            .and(Schedule.spaced(periodicity))
            .repeat {
                yield()
                //ball fetching logic here
            }
    }

Expected behavior:

When calling ballFetchingScope.cancel() all coroutines are cancelled and all fetching stops.
Ideally not even needing to wait until it reaches the yield() call, if it is waiting for the next run to happen, I would like for it to cancel and never that that run of the repeat block.

What is actually happening:

Fetching continues to happen normally.



Solution

It’s a bit hard to say here what is going on.

It’s very strange that this is not working for you, since Schedule relies on KotlinX kotlin.coroutines.delay to execute the Schedule.spaced. So it should get cancelled while waiting for the next run.

It also checks coroutineContext.ensureActive() before running the function passed to repeat so it also automatically check in the place where you now manually placed yield.

Which version of Arrow are you using? And could you share a fully reproducible example?


This Question was asked in StackOverflow by LeYAUable and Answered by nomisRev It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?