简体   繁体   中英

how to write batched transactions for firebase admin realtime db?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM