Dangling transaction even though commit is called (node,Sequelize v5.21.9)

440 Views Asked by At

I have a route that uses the below shown method, in a node app that uses express.

I create a transaction but don't use it in the update method. Sequelize is configured to not use managed transactions and auto commit is set to false.

When this route is called multiple times/under load around 7 - 10 times per second (the number of calls differ), I end up with 5 or so dangling transactions even though commit is called for the transaction at the end of the method call. (Because of these dangling transactions, subsequent calls and my node app is not able to make anymore db calls)

But if I pass the transaction in the params object this behaviour doesnt occur. And I don't get dangling transactions.

What can be the reason this is happening?

    updateItem = (obj) => {
        this.logDebug(`Updating item - `, obj);

        return new Promise(async (resolve, reject) => {

            let transaction;
            try {
                transaction = await this.getTransaction();
            } catch(error) { return reject(error);


            const params = {
               where: {
                   id: obj.id
               },
               returning: true,
               plain: true
            };

            return models[modelName].
             update(obj, params).then(result => {
                   if (!result) { return result; }

                   result = JSON.parse(JSON.stringify(result[1]));
                   return result;
                }).
                then(async (result) => {
                    await transaction.commit();
                    return resolve(result);
                }).
                catch(async error => {
                    this.logError(`Failed to update - `, error);
                    await transaction.rollback();
                    return reject(error);
                });
        });
    };

Causes dangling transaction.


const params = {
   where: {
       id: obj.id
   },
   returning: true,
   plain: true
};

No dangling transactions occur.


const params = {
   where: {
       id: obj.id
   },
   returning: true,
   plain: true,
   transaction
};

Using Nodejs 12.4, Sequelize 5.21.9, postgres 9.x

Just using the created transaction in the params object somehow doesn't cause dangling transaction.
While NOT using the transaction in the params causes this issue of dangling transactions.

Wanted to know the cause of this behaviour? Is it a bug with my code? Or bug with Sequelize?

1

There are 1 best solutions below

0
On

There are a few points here;

1- there is a missing curly bracket at the end of the first line (a simple type i guess)
2- you dont't have to use the returns other than the first one
3- it is not required to use double "then" fucntion at the end
4- if json parse fails your transaction probably leak

With all these the code may be updated like this;

updateItem = (obj) => {
    this.logDebug(`Updating item - `, obj);

    return new Promise(async (resolve, reject) => {

        let transaction;
        try {
            transaction = await this.getTransaction();
        } catch (error) { return reject(error); }

        const params = {
            where: {
                id: obj.id
            },
            returning: true,
            plain: true
        };

        return models[modelName].
            update(obj, params).then(async (result) => {
                try {
                    resolve(JSON.parse(JSON.stringify(result[1])));
                    await transaction.commit();
                } catch (err) {
                    reject(err);
                }
            }).catch(async error => {
                this.logError(`Failed to update - `, error);
                await transaction.rollback(); // an extra try catch wont hurt here...
                reject(error);
            });
    });
};

But things may get complicated if you want to make multiple updates in the future. I may suggest you to check Multiple Transaction Manager's Sequelize context for a clean way to arrange your transactions.