Ответы SnapshotListener обновления Firestore выходят из строя даже при ожидании .get ()

Запуск приветственного мира записи нескольких последовательных значений true / false в базу данных firestore с целью синхронизации локальной переменной с облаком.

События обратного вызова кажутся неупорядоченными, даже когда каждый вызов update() ждет, прежде чем начать следующий с помощью get().

Я пишу "ложь", "правда", "правда" Но ОТВЕТЫ бывают «истина», «ложь», «истина».

Что еще более странно, иногда бывает 3 ответа, даже когда я сделал только 2 запроса. Возможно, что-то встанет в очередь на следующий раз, когда я запущу приложение? Если да, то есть ли способ обязательно промыть перед выключением?

Меня беспокоит то, что в моем локальном приложении может остаться неверное представление о самом последнем значении.

import com.google.auth.oauth2.GoogleCredentials
import com.google.cloud.firestore.FirestoreOptions
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val firestoreOptions = FirestoreOptions.newBuilder()
            .setCredentials(GoogleCredentials.fromStream(
                    ClassLoader.getSystemClassLoader().getResourceAsStream("serviceAccountKey.json")))
            .setTimestampsInSnapshotsEnabled(true)
            .build()
    val db = firestoreOptions.service!!

    val docRef = db.collection("users").document("tmpUser").collection("devices").document("tmpDevice")
    docRef.addSnapshotListener { snapshot, _ ->
        (snapshot?.data ?: mapOf()).forEach { key, value ->
            println("  RESPONSE: '$key'='$value'")
        }
    }
    println("Listening...")

    val writeResultFuture2 = docRef.update(mapOf("running" to false))
    println("REQUEST 'false' at ${writeResultFuture2.get().updateTime}")

    val writeResultFuture3 = docRef.update(mapOf("running" to true))
    println("REQUEST 'true' at ${writeResultFuture3.get().updateTime}")

    val writeResultFuture4 = docRef.update(mapOf("running" to true))
    println("REQUEST 'true' at ${writeResultFuture4.get().updateTime}")

    delay(5_000)
    println("Stopping.")
}

Выход:

Listening...
  RESPONSE: 'running'='true'
  RESPONSE: 'running'='false'
REQUEST 'false' at 2018-10-12T21:07:25.530943000Z
REQUEST 'true' at 2018-10-12T21:07:25.686950000Z
  RESPONSE: 'running'='true'
REQUEST 'true' at 2018-10-12T21:07:25.686950000Z
Stopping.

Можете ли вы распечатать журнал вашего последнего запуска с помощью этого кода?

Todd Kerpelman 12.10.2018 22:24

@ToddKerpelman отредактировал, чтобы включить вывод.

Benjamin H 12.10.2018 23:08
Интеграция Angular - Firebase Analytics
Интеграция Angular - Firebase Analytics
Узнайте, как настроить Firebase Analytics и отслеживать поведение пользователей в вашем приложении Angular.
0
2
165
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, краткий ответ: похоже, это работает так, как задумано.

Во-первых, имейте в виду, что когда вы создаете updateListener, он будет запускаться не только при обновлениях, но и в первый раз с любыми данными, уже существующими в базе данных. (И это обычно то, что вы хотите - это значительно упрощает написание вашего кода, потому что вы просто создаете свой обработчик как обработчик «Все данные из базы данных», будь то первоначальное извлечение или обновление.) Итак, это почему вы получаете этот первый «истинный» ответ.

Второй «ложный» ответ - это первое применяемое вами обновление.

Третий «истинный» ответ - это второе обновление, которое вы применяете.

Четвертый «истинный» ответ никогда не запускается, потому что клиентский SDK обычно достаточно умен, чтобы не вызывать обработчик снова, если данные из базы данных в точности совпадают с данными, которые уже существуют. Я предполагаю, что если бы этот третий вызов обновления был изменен на что-то вроде «Может быть», то вы бы увидели четвертый ответ.

Другие вопросы по теме