is there a way to perform batched transactions on different fields in realtime database with admin sdk? Currently, I'm using the following:
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)
})
}
but every time this function is called, although the transactions do work as a batch, the following error is thrown:
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)
You can't pass a bunch of transactions into a update()
call, which is what the error message is (admittedly somewhat confusingly) is trying to tell you.
Firebase has no concept of nested, or batched, transactions. If you need to perform a transaction over multiple locations, you will need to run this as a single transaction
call over a node that is above all those locations. As you can probably guess, the contention on such a multi-location transaction is very quickly going to be a throughput limit, so you'll want to consider alternative solutions.
The "simplest" approach I can think of for your use-case, is to replace the two transactions with a single multi-location update, and then use server-side security rules to validate the operation.
For an example of how to do something similar, see my answer here: Is the way the Firebase database quickstart handles counts secure?
With this approach you prevent most of the contention, as the multi-location update doesn't need to read-send-check the entire top-level node, but merely the lower-level nodes that you're updating.
You may have to modify you data structure, and possibly even write additional data, to allow this approach. But in return you'll get a much more scalable transactional update.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.