关于休息api的交易

时间:2017-10-05 14:00:57

标签: node.js postgresql transactions sequelize.js database-migration

我正在开发一个项目,我需要实现事务以使用Nodejs在REST操作中回滚PostgreSQL数据库。我已经为GET,PUT和POST方法分别实现了事务。我需要使用一次交易还是我在正确的轨道上? 在此先感谢您的帮助。

如果需要,我想确保我的数据库回滚数据。我正在使用pg-promise库来获得结果。

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;
});

或者,我应该实施以下方法吗?

    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 });
  }),
};

提前谢谢你。

3 个答案:

答案 0 :(得分:2)

我建议您使用Bookshelf,这是在Knex查询构建器上运行的非常成熟的ORM。 Bookshelf提供了一个事务API,如果调用代码中的任何“拒绝”,它将进行回滚。例如:

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)'));

这里我只是创建一个deleteUsers()函数,它接收一个ids数组,然后启动一个transaction开始寻找用户,然后删除它们。如果找不到任何用户或其中一个DELETE操作失败,则会有回滚。

答案 1 :(得分:1)

Sequelizejs'docs表明你的第一种方式还可以。为了更好的控制,我会选择第二名。休息,nodejs - 这意味着微服务。即使不是 - 我觉得每个请求的单个交易是正确的方式。

如果你需要更好地控制“工作单位”,那么,也许我会将它们作为单独的交易。这会给数据库带来额外的负担,所以如果不需要,我就不会这样做。

答案 2 :(得分:0)

看起来所有代码示例都有效。

据我所知,事务中的所有操作必须使用相同的连接执行,

所以,即使您不等到第一个请求结束 - 第二个请求也不会在第一个请求完成之前启动(在库级别,因为它们使用相同的连接,并且连接只能处理parralel中的1个请求)< / p>

所以不要担心......

为了加快执行速度,您可以打开多个连接并以并行方式执行多个事务