Как исправить «слишком много разногласий» в onCreate, инициированном пакетной записью - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть школьный предмет с классами и учениками. Студенты - это подгруппа каждой семьи. При создании школы я пишу несколько сотен семей в нескольких сериях записей.

Создавая каждого учащегося, я хочу сделать несколько вещей:

  • обновить строку в семье учащегося содержит имена учеников
  • ученики содержат идентификатор класса, и я sh обновлю класс с некоторыми данными ученика
  • школа ведет отдельный список учеников для удобства поиска, и Я хочу добавить туда студентов

Этот код выглядит следующим образом ...

exports.didCreateStudent = functions.firestore.document(studentPath).onCreate((snap, context) => {
  return Promise.all([
    updateFamilyNames(snap.ref.parent.parent),
    updateClassroomStudent(snap, null, snap.data().classroom),
    updateStudentCollection(null, snap)
  ])
})

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

Например, существенная часть updateClassroomStudent выглядит следующим образом ...

  return transaction.get(classroomDocRef).then(snapshot => {
    const student = Object.assign({}, _.pick(studentSnapshot.data(), 'firstName', 'lastName', 'grade'), { ref: studentSnapshot.ref })
    const addition = { students: { [studentSnapshot.id]: student } }
    return transaction.set(snapshot.ref, addition, { merge: true })
  })

Это хорошо работает для небольших школ (10 семей, примерно по 2 ученика в каждой), но в больших школах (100 семей) я начинаю видеть Error: 10 ABORTED: Too much contention on these documents. Please try again.

Я могу избежать ошибок, пропустив оба updateClassroomStudent и updateStudentCollection, но нет, если я разрешу запускать один (или оба).

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

1 Ответ

0 голосов
/ 27 апреля 2020

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

. Я предлагаю также прочитать это, которое покрывает ту же ошибку, с другим вариантом использования: Ошибка: 10 ABORTED: Слишком много разногласий на этих документах. Пожалуйста, попробуйте еще раз

Под «разногласиями» я подразумеваю, что существует много одновременного доступа к документу посредством транзакции. Обработчик транзакции повторяется слишком много раз из-за всех записей. Это поведение указано в документации :

В случае одновременного редактирования Cloud Firestore снова запускает всю транзакцию. Например, если транзакция читает документы, а другой клиент изменяет какой-либо из этих документов, Cloud Firestore повторяет транзакцию. Эта функция гарантирует, что транзакция выполняется на актуальных и согласованных данных.

Позже сообщает, что транзакция может завершиться неудачей, когда :

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

Не видя весь ваш код, трудно порекомендовать курс действий, но я думаю, что ключом будет попытка изменить способ работы вашей схемы. применяя все обновления к документу в одной транзакции, а не позволяя множеству транзакций сталкиваться из-за множества обновлений.

Еще один гораздо более масштабируемый вариант - хранить список студентов в виде отдельных документов во вложенной коллекции, а не чем в виде списка в одном документе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...