Как обновить тот же документ с помощью чтения из той же коллекции в функции onUpdate - PullRequest
0 голосов
/ 24 июня 2019

Я пытаюсь обновить тот же документ, который вызвал облачную функцию onUpdate, значением чтения из той же коллекции. Это приложение для чата, созданное во Flutter, где предыдущий ответ на запрос реплицируется в обновляемый документ, чтобы его было проще увидеть в приложении.

Код работает, однако, когда пользователь быстро отвечает на два отдельных запроса, они оба читают один и тот же последний ответ, устанавливая тот же предыдущий ответ. Это должно быть связано с асинхронной природой трепетания и / или облачной функции, но я не могу понять, где ждать или есть лучший способ сделать функцию, поэтому она никогда не вызывает onUpdate для того же пользователя, пока предыдущий триггер не закончен. Последняя часть также звучит как плохая идея.

До сих пор я пытался привязать чтение / обновление к транзакции, однако, похоже, это работает только для одного вызова функции, а не тогда, когда они асинхронны. Также решил, что я мог бы это исправить, прочитав предыдущий ответ в транзакции на клиенте, однако Firebase не позволяет читать из коллекции в транзакции, когда не используется серверный API.

async function setPreviousResponseToInquiry(
  senderUid: string, 
  recipientUid: string, 
  inquiryId: string) {

    return admin.firestore().collection('/inquiries')
    .where('recipientUid', '==', recipientUid)
    .where('senderUid', '==', senderUid)
    .where('responded', '==', true)
    .orderBy('modified', 'desc')
    .limit(2)
    .get().then(snapshot => {
      if (!snapshot.empty && 
          snapshot.docs.length >= 2) {
        return admin.firestore()
          .doc(`/inquiries/${inquiryId}`)
          .get().then(snap => {
          return snap.ref.update({ 
            previousResponse: snapshot.docs[1].data().response 
          })
        })
      }
    })
}

1 Ответ

0 голосов
/ 24 июня 2019

Я вижу три возможных решения:

  1. Используйте транзакцию на сервере, которая гарантирует, что записываемое вами обновление должно основываться на версии прочитанных вами данных. Если значение, которое вы вводите, зависит от данных, которые запускают облачную функцию, вам может потребоваться перечитать эти данные как часть транзакции.
  2. Не используйте облачные функции, но запускайте все обновления с клиента. Это позволяет использовать транзакции для предотвращения состояния гонки.
  3. Если невозможно использовать транзакцию, возможно, вам придется включить пользовательский номер версии как в исходные данные (данные, которые инициируют запись), так и в разветвленные данные, которые вы обновляете. Затем вы можете использовать правила безопасности, чтобы гарантировать, что нисходящие данные могут быть записаны, только если их версия соответствует текущим вышестоящим данным.

Я бы рассмотрел / попробовал их в вышеуказанном порядке, так как они постепенно становятся более вовлеченными.

...