Firestore возвращает пустой снимок несуществующих данных без интернета - PullRequest
0 голосов
/ 04 августа 2020

Firestore и RTDB ведут себя по-разному при попытке прослушивания без rnet. RTDB не запускает никаких слушателей, пока inte rnet не будет восстановлен. Firestore запускает прослушиватель с пустым снимком, поэтому вызов exists () возвращает false. Когда inte rnet восстанавливается, Firestore снова запускается с живыми данными. Это приложение без сохранения на диске, и читаемые поля / документы никогда не записывались до того, как были установлены слушатели.

То, что делает firestore, может сильно сбивать с толку ... Возможно, невозможно сказать действительно ли данные не существуют или что-то еще пошло не так. Это предполагаемое поведение и есть ли способ обойти это?

//first firestore statement in the app
fs.collection("blabla").document("blabla").addSnapshotListener(new EventListener<DocumentSnapshot>() {
    @Override
    public void onEvent(@Nullable DocumentSnapshot value, @Nullable FirebaseFirestoreException error)
    {
        if (error == null)
            Log.v("TEST", "FS LISTEN EVENT " + value.exists() + " " + value.getData());
        if (error != null)
            Log.v("TEST", "FS LISTEN ERROR " + error);
    }
});

Logcat:

V / TEST: FS LISTEN EVENT false null

After inte rnet восстановлено:

V / TEST: FS LISTEN ERROR com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Отсутствуют или недостаточны разрешения.

EDIT:

Я проверил это сейчас с настойчивостью и без нее. Идентичное поведение, по крайней мере, при первом получении этих данных. Поскольку я не собираюсь использовать постоянство диска, это будет происходить каждый раз при создании действия.

Я могу использовать get () вместо прослушивателя снимков - он возвращает хороший com.google.firebase.firestore. FirebaseFirestoreException: не удалось получить документ, поскольку клиент отключен. Совершенно другое поведение. Но у меня также есть оговорки по поводу get ():

  1. Нет возможности остановить / отменить регистрацию. Поэтому я не могу реализовать тайм-аут для этой операции. Он может сработать, когда приложение приостановлено - или в любой другой неожиданный момент. Нет goOffline с firestore ... Да, я мог бы придумать logi c, чтобы справиться с этим - конечно, это сложно, хотя ...

  2. Так и не получил ответа, проблема с холодным огнем решена. Некоторые люди записывали 90 секунд для get () для получения данных. Для некоторой критически важной части данных, необходимой при загрузке приложения, и невозможности реализовать тайм-аут - как справиться с потоком приложения?

Ответы [ 2 ]

0 голосов
/ 07 августа 2020

Возможно, удастся определить, был ли возвращенный нулевой снимок вызван проблемами сети, просмотрев метаданные снимка (предложение Фрэнка). Если постоянство отключено, записи в это место не выполнялись и возвращается нулевой снимок, но metadata.isFromCache () возвращает true, тогда я думаю, можно предположить, что Firestore просто не смог получить данные с сервера. И наоборот, если metadata.isFromCache () имеет значение false, документ не существует.

fs.collection("users").document(mAuth.getCurrentUser().getUid()).addSnapshotListener(MetadataChanges.INCLUDE, new EventListener<DocumentSnapshot>()
        {
            @Override
            public void onEvent(@Nullable DocumentSnapshot value, @Nullable FirebaseFirestoreException error)
            {
                if (value != null)
                    Log.v("TEST", "FS LISTEN EVENT, exists: " + value.exists() + " data: " + value.getData() + " from cache: " + value.getMetadata().isFromCache());
                if (error != null)
                    Log.v("TEST", "FS LISTEN ERROR " + error);
            }
        });
0 голосов
/ 04 августа 2020

Поведение, которое вы видите, является нормальным и ожидаемым.

Правила безопасности применяются только на сервере, а не в кэше на стороне клиента.

Лог c вот что касается чтения, поскольку клиент видел данные в какой-то момент, они продолжают быть видимыми. Для записи это вопрос разрешения быстрого обновления пользовательского интерфейса. Если вы хотите, вы можете показать, что запись ожидает обработки, отразив hasPendingWrites в вашем пользовательском интерфейсе.

Здесь происходит следующее:

  1. Клиент фиксирует запись в свой локальный кеш
  2. Клиент запускает локальные события для операции записи, чтобы приложение могло обновить свое состояние.
  3. Клиент отправляет запись на сервер
  4. Сервер отклоняет операцию записи и отправляет отрицательный ответ клиенту.
  5. Клиент обновляет свое локальное состояние и запускает событие (я) согласования, чтобы приложение также могло обновить свое состояние.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...