Мы столкнулись с той же проблемой с базой данных Firebase Firestore.Даже небольшие фишки с менее чем 30 предметами, которые можно найти, сталкиваются с этой проблемой.
Наше решение состояло не в том, чтобы распределить счетчик, а в том, чтобы увеличить число попыток транзакции и добавить время задержки для этих повторных попыток.
Первым шагом было сохранение действия транзакции какconst witch может быть передана другой функции.
const taskCountTransaction = async transaction => {
const taskDoc = await transaction.get(taskRef)
if (taskDoc.exists) {
let increment = 0
if (change.after.exists && !change.before.exists) {
increment = 1
} else if (!change.after.exists && change.before.exists) {
increment = -1
}
let newCount = (taskDoc.data()['itemsCount'] || 0) + increment
return await transaction.update(taskRef, { itemsCount: newCount > 0 ? newCount : 0 })
}
return null
}
Вторым шагом было создание двух вспомогательных функций.Один для ожидания определенного количества времени, другой для запуска транзакции и обнаружения ошибок.Если возникает ошибка сброса с кодом 10. Мы просто запускаем транзакцию снова для определенного количества попыток.
const wait = ms => { return new Promise(resolve => setTimeout(resolve, ms))}
const runTransaction = async (taskCountTransaction, retry = 0) => {
try {
await fs.runTransaction(taskCountTransaction)
return null
} catch (e) {
console.warn(e)
if (e.code === 10) {
console.log(`Transaction abort error! Runing it again after ${retry} retries.`)
if (retry < 4) {
await wait(1000)
return runTransaction(taskCountTransaction, ++retry)
}
}
}
}
Теперь, когда у нас есть все, что нам нужно, мы можем просто вызвать нашу вспомогательную функцию с помощью await
инаш вызов транзакции будет выполняться дольше, чем вызов по умолчанию, и он будет задерживаться во времени.
await runTransaction(taskCountTransaction)
Что мне нравится в этом решении, так это то, что оно не означает более сложный код и что большая часть уже написанногокод может остаться как есть.Он также использует больше времени и ресурсов только в том случае, если счетчик доходит до того, что ему приходится считать больше предметов.В противном случае время и ресурсы такие же, как если бы у вас были транзакции по умолчанию.
Для увеличения количества элементов мы можем увеличить количество повторных попыток или время ожидания.Оба также влияют на стоимость Firebase.Для части ожидания нам также нужно увеличить время ожидания для нашей функции.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ : я не тестировал этот код со стрессом с тысячами или более элементов.В нашем конкретном случае проблемы начались с 20+ предметов, и нам нужно до 50 предметов для задачи.Я проверил это с 200 пунктами, и проблема не появлялась снова.