Как написать пакетные транзакции для администратора базы данных Firebase в реальном времени? - PullRequest
0 голосов
/ 08 февраля 2020

Есть ли способ выполнить пакетные транзакции на разных полях в базе данных в реальном времени с администратором SDK? В настоящее время я использую следующее:

exports.function = functions.https.onCall((data, context) => {

    var transactions = new Object();

    transactions[0] = admin.database().ref('ref1/')
        .transaction(currentCount => {
            return (currentCount || 0) + 1;
        }, (error, committed, dataSnapshot) => {...})

    transactions[1] = admin.database().ref('ref2/')
        .transaction(currentCount => {
            return (currentCount || 0) + 1;
        }, (error, committed, dataSnapshot) => {...})

    return admin.database().ref().update(transactions)
                             //  |^|  error occurs right above '|^|', but i don't know why, i suspect it may have something to do with transactions object, and if so, what's the proper way to do batched transactions?
        .then(result => {...})
        .catch(error => {
            console.error('error: ' + error)
        })
}

, но каждый раз, когда эта функция вызывается, хотя транзакции работают как пакет, выдается следующая ошибка:

Unhandled error TypeError: obj.hasOwnProperty is not a function
    at each (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:541:17)
    at validateFirebaseData (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:1470:9)
    at /srv/node_modules/@firebase/database/dist/index.node.cjs.js:1487:13
    at each (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:542:13)
    at validateFirebaseData (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:1470:9)
    at /srv/node_modules/@firebase/database/dist/index.node.cjs.js:1559:9
    at each (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:542:13)
    at validateFirebaseMergeDataArg (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:1557:5)
    at Reference.update (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:13695:9)
    at admin.firestore.collection.doc.collection.doc.create.then.writeResult (/srv/index.js:447:43)

1 Ответ

1 голос
/ 08 февраля 2020

Вы не можете передать несколько транзакций в вызов update(), о котором пытается сообщить вам сообщение об ошибке (по общему признанию, несколько сбивающее с толку).

Firebase не имеет понятия вложенного, или пакетные транзакции. Если вам нужно выполнить транзакцию в нескольких местах, вам нужно будет выполнить ее как один transaction вызов через узел, который находится над всеми этими местоположениями. Как вы, вероятно, можете догадаться, конкуренция за такую ​​многопозиционную транзакцию очень скоро станет пределом пропускной способности, поэтому вам следует рассмотреть альтернативные решения.

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

Пример того, как сделать нечто подобное, см. в разделе мой ответ здесь: Безопасен ли способ быстрого запуска базы данных Firebase?

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

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

...