База данных Firebase Realtime - периодически update () работает как set () - PullRequest
0 голосов
/ 21 декабря 2018

Время от времени и непредсказуемо, функция базы данных Firebase Realtime update(), похоже, работает как функция set().Как ни странно, это происходит примерно на 1% операций обновления.Но мы выполнили подробное ведение журнала и увидим, что такие вещи происходят из-за того, что конкретное обновление передается группе пользователей внутри цикла, мы проверяем, что в журналах всем им отправляется правильная информация, и update() вызывается на каждой записи.Однако в результате мы увидим, что иногда один из пользователей получит запись, содержащую только те поля, которые мы обновили, и все остальные поля в записи будут удалены, а все остальные пользователи получат обновление должным образом.Последующее выполнение точно такой же операции update() приведет к тому, что все будет обновлено, как ожидается.Это известная проблема?Есть ли обходные пути?Мы запускаем firebase-admin 6.0.0 на узле 8.14.0

Попытка многократных повторных тестов функции update ().Не существует надежного способа заставить эту проблему воспроизводиться, но это происходит случайным образом в производственном процессе.

const contactsRef = admin.database().ref().child('contacts');
...
//targetUID, contactID, contactObj get passed in via PubSub
...
contactsRef.child(targetUID).child(contactID).update(contactObj);

Ожидается: update() должен обновлять только поля записи, передаваемые ему.

Actual: update(), кажется, работает как set() в случайном порядке, примерно в 1% случаев.Любые поля, которые не включены в объект, передаваемый в update(), удаляются из целевой записи в базе данных реального времени.

1 Ответ

0 голосов
/ 21 декабря 2018

Очень маловероятно, что сервер баз данных ведет себя по-разному для 1% ваших пользователей.Гораздо более вероятно, что есть небольшая разница в вызовах, которые совершает 1% ваших пользователей.Трудно быть уверенным в том, что это отличие от кода, которым вы поделились, поэтому ниже приведено обоснованное предположение в надежде быстро разблокировать вас.

Вы говорите, что делаете:

contactsRef.child(targetUID).child(contactID).update(contactObj);

Ожидается: update() должен только обновлять передаваемые ему поля записи.

Это немного неуловимо, и, к сожалению, вы не показываете, как вы строите contactObj.Поэтому я приведу пример.Скажем, вы начинаете с JSON:

"uid1": {
  "name": "unknown",
  "id": -1,
  "full_name": "unknown",
  "metadata": {
    "last_seen": "20 minutes ago",
    "reputation" 56
  }
}

И запускаете это в этом месте:

ref.update{
  "name": "miles_b",
  "id": 2687721
}

В этом случае только свойства name и id в refобновляются.Другие свойства не изменены, поэтому вы получите:

"uid1": {
  "name": "miles_b",
  "id": 2687721,
  "full_name": "unknown",
  "metadata": {
    "last_seen": "20 minutes ago",
    "reputation" 56
  }
}

Но теперь скажите, что вы также хотите обновить metadata/reputation.Вы можете подумать, что это работает:

ref.update{
  "name": "miles_b",
  "id": 2687721,
  "metadata": {
    "reputation": 61
  }
}

Но здесь вы говорите базе данных заменить metadata на предоставленный вами объект.В результате получается:

"uid1": {
  "name": "miles_b",
  "id": 2687721,
  "full_name": "unknown",
  "metadata": {
    "reputation" 61
  }
}

И это означает, что last_seen теперь удалено из базы данных.

Чтобы обновить вложенное свойство, включите его полный путь в ключ.Итак:

ref.update{
  "name": "miles_b",
  "id": 2687721,
  "metadata/reputation": 61
}

И с этим, вы будете сохранять metadata/last_seen при обновлении metadata/reputation:

"uid1": {
  "name": "miles_b",
  "id": 2687721,
  "full_name": "unknown",
  "metadata": {
    "last_seen": "20 minutes ago",
    "reputation" 61
  }
}
...