Home > Enterprise >  How to run a Firebase Transaction using Kotlin Coroutines?
How to run a Firebase Transaction using Kotlin Coroutines?

Time:10-22

I'm trying to run a Firebase Transaction under a suspended function in Kotlin and i see no documentation about it.

I'm using

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.5.2'

for coroutines with firebase (eg: setValue(*).await() ) but there seems to be no await function for runTransaction(*)

override suspend fun modifyProductStock(
    product: ProductModel,
    valueToModify: Long,
    replace: Boolean
) {
    CoroutineScope(Dispatchers.Main).launch {
        val restaurantId = authRepository.restaurantId.value ?: throw Exception("No restaurant!")

        val productId = product.id ?: throw Exception("No Product ID!")

        val reference = FirebaseDatabase.getInstance().getReference("database/$restaurantId").child("products")

        if (replace) {
            reference.child(productId).child("stock").setValue(valueToModify).await()
        } else {
            reference.child(productId).child("stock")
                .runTransaction(object : Transaction.Handler {

                    override fun doTransaction(p0: MutableData): Transaction.Result {
                        //any operation
                        return Transaction.success(p0)
                    }

                    override fun onComplete(p0: DatabaseError?, p1: Boolean, p2: DataSnapshot?) {
                    }

                })
        }
    }
}

CodePudding user response:

You could wrap it in suspendCoroutine:

val result: DataSnapshot? = suspendCoroutine { c ->
    reference.child(productId).child("stock")
        .runTransaction(object : Transaction.Handler {
            override fun doTransaction(p0: MutableData): Transaction.Result {
                //any operation
                return Transaction.success(p0)
            }
    
            override fun onComplete(error: DatabaseError?, p1: Boolean, snapshot: DataSnapshot?) {
                c.resume(snapshot)
            }
        })
}

suspendCoroutine

Obtains the current continuation instance inside suspend functions and suspends the currently running coroutine.
In this function both Continuation.resume and Continuation.resumeWithException can be used either synchronously in the same stack-frame where the suspension function is run or asynchronously later in the same thread or from a different thread of execution.

CodePudding user response:

Given that the Kotlin example in the Firebase documentation on transactions uses the same callback style that you have, it seems indeed that there is no specific support for co-routines there.

It might be worth posting an issue on the Android SDK repo to get it added, or hear why it wasn't added.

  • Related