Florian Ludewig
Florian Ludewig

Reputation: 5982

Node.js / Mongoose - Undo Database Modifications on Error

I have quite a complex express route in my node.js server, that makes many modifications to the database via mongoose.

My goal is to implement a mechanism, that reverts all changes when any error occurs. My idea was implementing functions for undoing into the catch block.

But this is quite ugly, as I have to know what the previous values were and what if an error occurs in the catch block? It's especially difficult to revert those changes, when an error occurred during a Promise.all(array.map( /* ... */ ))


My route looks akin to this:

module.exports = (req, res) => {

    var arr1, var2, var3

    try {

        const body = req.body

        arr1 = await fetchVar1(body)
        const _data = await Promise.all([
            Promise.all(
                arr1.map(async x => {
                    const y = await fetchSometing(x)
                    return doSometing(y)
                })
            ),
            doSomething3(arr1),
        ])
        var2 = _data[1]
        var3 = _data[2]

        return res.json({ arr1, var2, var3 })

    } catch (err) {

        /**
         * If an error occurs I have to undo
         * everything that has been done
         * in the try block
         */

    }
}

Preferably I would like to implement something that "batches" all changes and "commits" the changes if no errors occurred.

Upvotes: 4

Views: 3044

Answers (2)

frsechet
frsechet

Reputation: 790

What you are looking for is transactions: https://mongoosejs.com/docs/transactions.html

Manually undoing stuff after doing them won't protect you from every issue, so you should not rely on that. For example, exactly as you wrote: what happens if there is a crash after a partial write (some data is written, some is not), then another crash during your "rollback" code, which does not cleanup everything? If your code depends on your data being absolutely clean, then you have a problem. Your code should either be able to handle partial data correctly, or you must have some way to guarantee that your data is perfectly good at all times.

Transactions is the way to go, because it only commits everything at once if everything works.

Upvotes: 7

Tarek
Tarek

Reputation: 140

What you’re looking for is called Transactions.

Transactions are new in MongoDB 4.0 and Mongoose 5.2.0. Transactions let you execute multiple operations in isolation and potentially undo all the operations if one of them fails. This guide will get you started using transactions with Mongoose.

For more information check the link below: https://mongoosejs.com/docs/transactions.html

Upvotes: 4

Related Questions