Home > Enterprise >  Kotlin Arrow-kt - why are my coroutines not cancelling properly?
Kotlin Arrow-kt - why are my coroutines not cancelling properly?

Time:09-20

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 not even start a new run of the repeat block.

What is actually happening:

Fetching continues to happen normally.

CodePudding user response:

I am answering my own post just to make sure you are not making the same dumb mistake I was making.

Everything was working as supposed, the issue was on my side. I had two different instances of the class containing the ballFetchingScope

This means that I was calling the ballFetchingScope.cancel() on the scope for one of those instances while the Coroutines were running on the scope in the other instance.

Botom-line: Make sure you are not using multiple instances when you think you have only one.

CodePudding user response:

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?

  • Related