Transaction on rest api

I am working on a project where I need to implement transaction to rollback PostgreSQL database durin REST operation using Nodejs. I have implemented transaction separately for GET, PUT and POST methods. Do I need to use transaction once or am i on a right track? Thanks in advance for your help.

I want to ensure my database rollback data if it is needed. I am using pg-promise library to get the result.

db.tx(t => {
    return t.batch([
        t.query('UPDATE users SET active = $1 WHERE id = $2', [true, 123]),
        t.query('INSERT INTO audit(event, id) VALUES($1, $2)', ['activate', 123])
    ]);
})
.then(data => {
    // success;
})
.catch(error => {
    // error;
});

Or, should I implement below method?

    module.exports = { 
  // if you can run all migration queries simultaneously  
  up: ({ sequelize: db }) => db.transaction(transaction => Promise.all([
    db.query('...', { transaction }),
    db.query('...', { transaction }),
  ])),

  // If you have to wait for every query before executing next one
  down: ({ sequelize: db }) => db.transaction(async (transaction) => {
    await db.query('...', { transaction });
    await db.query('...', { transaction });
  }),
};

Thank you in advance.


I recommend you to use Bookshelf, it's a very mature ORM running over the Knex query builder. Bookshelf provide a transaction API which will make a rollback if any "rejection" in the code is called. Eg:

const knex = require('knex')({
  client: 'pg',
  connection: {
    host: '127.0.0.1',
    user: 'user',
    password: 'password',
    database: 'db',
    charset: 'utf8'
  }
});

const bookshelf = require('bookshelf')(knex);

const User = bookshelf.Model.extend({
  tableName: 'users'
});

const deleteUsers = ids =>
  bookshelf.transaction(transacting =>
    Promise.map(ids, id => User.forge({ id })
      .fetch({ transacting })
      .then((user) => {
        if (!user) return Promise.reject(new Error('User not found (this is a rollback)'));

        return user.destroy({ transacting }); // If something wrong happens here, a rollback is called
      })))
    .then(() => Promise.resolve('Transaction Complete! (this is a commit)'));

Here I'm just making a deleteUsers() function which receives an array of ids , then start a transaction to start looking for the users and then delete them. If any user is not found or one of the DELETE operations fails there will be a rollback.


Sequelizejs' docs shows that your first way is OK. I would go for second, for better control. Rest, nodejs - that means microservices. Even if not - I feel that single transaction per request is the right way.

If you need better control on what goes as "unit of work", then, perhaps I would put them as separate transactions. That puts additional load to the DB, so I would not go that way, if not needed.


Looks like all code samples are valid.

As far as I understand all operations in transaction MUST be executed with the same connection,

So even if you will not wait till the end of first request - second request will not start before first request is finished (on the library level, as they use same connection, and connection can process only 1 request in parralel)

So don't worry...

For faster execution, you may open several connections and do a several transactions in parrallel

链接地址: http://www.djcxy.com/p/40588.html

上一篇: 等于和循环引用:如何解决无限递归?

下一篇: 交易休息api