I'm using `suspendCancellableCoroutine` to suspend...
# coroutines
j
I'm using
suspendCancellableCoroutine
to suspend a coroutine awaiting the results of a callback API to resume the coroutine with:
Copy code
val result = suspendCancellableCoroutine { continuation ->
    callbackApi {
        continuation.resume(it)
    }
}
This works as expected the first time the code is called, but the second time the code is executed
continuation.resume()
doesn't work.
continuation.isActive
is false,
continuation.isCompleted
and
continuation.isCancelled
are true. Is it wrong to expect an active continuation after calling
suspendCancellableCoroutine
? Even after wrapping the code in
async
, launching a fresh coroutine, the continuation still isn't active the second time the code executes. What am I doing wrong?
e
Check your callback api, it might be capturing a stale lambda
Also show the surrounding code and or how callbackApi is implemented
j
I had the same thought, so I'm logging the other state captured in the lambda to confirm it is the new lambda. I'm hoping after getting some sleep, I'll see something I missed this morning. 😅 I'll share more of the code.
My code and tests are based on the SQLDelight paging extension. The
suspendCancellableCoroutine
is used to suspend awaiting callback here. The failing tests were all calling this. If I replace
runTest
with
runBlocking
and the
withPagingDataDiffer
function with this:
Copy code
suspend fun <T : Any> PagingData<T>.withPagingDataDiffer(
    testScope: CoroutineScope,
    diffCallback: DiffUtil.ItemCallback<T>,
    block: AsyncPagingDataDiffer<T>.() -> Unit,
) {
    val pagingDataDiffer = AsyncPagingDataDiffer(
        diffCallback,
        NoopListCallback,
        mainDispatcher = Dispatchers.Default,
        workerDispatcher = Dispatchers.Default,
    )
    val job = testScope.launch {
        pagingDataDiffer.submitData(this@withPagingDataDiffer)
    }
    delay(100)
    block(pagingDataDiffer)
    job.cancel()
}
the tests now pass with the continuations behaving as expected.
Obviously I don't like the arbitrary
delay(100)
awaiting the database operations to be completed. I'll have to see if there's a better way to replace this.
I created an issue to track this.