Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Android: как остановить транзакцию Firestore?

Автор вопроса: JuniorОтветов: 1

Сначала я запрашиваю некоторые документы в Firestore, используя этот queryWaitingRoom(), и вызываю runTransactionInWaitingRoom(), если результат удовлетворяет условию.

Вот первая функция:

private fun queryWaitingRoom() {
    waitingRoomRef
        .orderBy("isAvailable", Query.Direction.DESCENDING)
        .limit(1)
        .get()
        .addOnSuccessListener { documents ->

            if (!documents.isEmpty){
                for (document in documents) {
                    val waitingRoomId = document.get("id").toString()

                    runTransactionInWaitingRoom(waitingRoomId)
                }
            }
        }
}

Мой вопрос: в runTransactionInWaitingRoom(), если значение currentState не равно true, как я могу остановить transaction прямо в блоке else? и снова позвонить в queryWaitingRoom()? Вот вторая функция:

 private fun runTransactionInWaitingRoom(waitingRoomId: String){
    val docRef = waitingRoomRef.document(waitingRoomId)

    db.runTransaction { transaction ->

        val snapshot = transaction.get(docRef)
        val currentState = snapshot.getBoolean("isAvailable")

        if (currentState == true){
            transaction.update(docRef, "isAvailable", false)
        } else {
            ///// STOP THE TRANSACTION RIGHT HERE /////
            ///// And call the the queryWaitingRoom() again /////

            Log.d("OIWENCLKSJF", "Transaction.currentState != true")   // getting called 5 or 6 times.

            throw FirebaseFirestoreException("Population too high",    // only get called at the last attemp.
                FirebaseFirestoreException.Code.ABORTED)
        }

    }.addOnSuccessListener {

    }.addOnFailureListener { e ->
        Log.w("OIWENCLKSJF", "Transaction failure.", e)
    }
}

Что я получил до сих пор, так это то, что transaction продолжает вызывать себя, даже если я бросаю exception в блок else. У меня есть аналогичный вопрос прямо здесь, в SO, но это не помогло. Я буду очень признателен, если кто-то может немного направить меня.

Firestore, как остановить транзакцию?

  • Пожалуйста, отредактируйте свой вопрос и добавьте структуру вашей базы данных в виде снимка экрана. Кроме того, является ли свойство isAvailable частью того же документа, что и id? Alex Mamo 14.10.2020
  • Я не думаю, что структура базы данных имеет какое-либо отношение к этой проблеме. И да, свойство isAvailable взято из того же документа. Также isAvailable может иметь только два значения.. true и false. При первом создании он получает значение true. Junior 14.10.2020

androidkotlingoogle-cloud-firestoretransactions

Ответы

Ответ 1 · рейтинг 1 · Alex Mamo

И да, свойство isAvailable взято из того же документа.

Если оба свойства относятся к одному и тому же документу, транзакция выполняется только в том случае, если свойство isAvailable имеет значение true:

if (!documents.isEmpty){
    for (document in documents) {
        val waitingRoomId = document.get("id").toString()
        val isAvailable = document.getBoolean("isAvailable")
        if(isAvailable) {
            runTransactionInWaitingRoom(waitingRoomId)
        }
    }
}

Идея этого решения заключается в том, чтобы выполнять транзакцию только, когда isAvailable истинно. То, что вы делаете сейчас, вы всегда запускаете транзакцию, а внутри нее, если условие не выполняется, отменяете транзакцию. Почему это решение невозможно? Представьте, что у вас есть 1 миллион документов, и только у 1 из них есть isAvailable true. Готовы ли вы запустить 1 миллион транзакций ради одного документа? Боюсь, это не так. Помните, что в Firestore каждое выполненное чтение документа стоит одну операцию чтения.

Решение, которое еще лучше, состоит в том, чтобы напрямую запросить в базе данных документы, в которых свойство isAvailable содержит значение true:

waitingRoomRef
    .whereEqualTo("isAvailable", true) //Added
    .orderBy("isAvailable", Query.Direction.DESCENDING)
    .limit(1)
    .get()

В этом случае вы сразу получите нужные документы. Стоимость этой операции будет равна количеству документов, которые возвращает запрос.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы