So, I have been trying to call a suspend function ...
# coroutines
p
So, I have been trying to call a suspend function from inside a consumer (functional interface). I get the
suspend function can be called from a coroutine
error. How to call a suspend function from inside a consumer?
Copy code
cluster.transactions().run { context ->
    setContextForDelete(node, context) // setContext... is a suspend function
}
h
The function of the consumer/functional interface needs to be suspending as well.
p
it is not a suspending function. it is a function in a library.
j
You either can call runBlocking and invoke directly, or send an item to a channel that is being consumed inside a coroutine as a signal to do the suspending work there.
p
I understand the run blocking approach. The other one is unfamiliar and sounds complicated to me. I usually avoid the run blocking route. The other option must be the right way.
blob nervous 1
@jw: is there a sample for the latter: “send an item to a channel that is being consumed inside a coroutine”
h
The cleanest option would be rewriting the transaction function to support coroutines, because a transaction is asynchronous too, you control the commit statement (indirectly called by the library). Is there another transaction api without a block but manual control? Then you can write a coroutines wrapper. If you need to run setContextOnDelete within the transaction, even the channel option won’t work, it would signal inside the transaction but the actual action would be done outside.
m
if you listener is one shot, you can do something like this:
Copy code
suspend fun someWork () {
    val result = CompletableDeferred<Context>()
    val listener = object : Transaction{
        override fun run(context: Context) {
            result.complete(context)
        }
    }
    try {
        addListener(listener)
        result.await()
    }finally {
        removeListener(listener)
    }
}
if the listener emits multiple values, you can replace the CompletableDeferred with a channel. Instead of result.await, use a for loop and do your work there