无法回滚Sequelize事务。

15
我正在尝试实现OAuth2,但我在Sequelize事务方面遇到了困难。
出现错误:
Executing (9edf48f7-5823-4b4f-b444-faa4c1896831): START TRANSACTION;
Executing (9edf48f7-5823-4b4f-b444-faa4c1896831): COMMIT;
Unhandled rejection Error: commit has been called on this
    transaction(9edf48f7-5823-4b4f-b444-faa4c1896831), you can no longer
    use it. (The rejected query is attached as the 'sql' property of
    this error)

以下是相关的JavaScript代码:
at.save({transaction: t}).then(() => {
                rt.save({transaction: t}).then(() => {
                    t.commit();
                    return done(false, accessToken, refreshToken, {
                        expires_at: expires,
                        scope: scope});
                }).error(function(
                    err) {
                    t.rollback();
                    return done(err);
                });
            }).error(function(err) {
                t.rollback();
                return done(err);
            });

我正在使用Sequelize 4.x.x与Postgres

1个回答

28

当您使用Sequelize事务并使用自动提交功能时,您需要确保返回每个查询的承诺。看起来您没有返回嵌套查询的承诺,这意味着您的原始承诺在第一个查询提交事务后解决。为了等待整个提交链完成,您必须返回嵌套承诺。

return sequelize.transaction(t => {
  return at.save({ transaction: t })
    .then(() => {
      return rt.save({ transaction: t })
        .then(() => {
          return t.commit() // Commit also returns a promise, you will want that to finish too
            .then(() => {
              return done();
            });
        });
    });
});

在我的例子中,你完全可以省略 t.commit() 的调用,因为 Sequelize 会自动提交事务,如果 promise 链解决了的话。如果你没有使用回调函数风格来处理事务,则应保留该语句。在我的例子中,我使用了回调函数风格。
祝你好运! :)

5
根据 Sequelize 的这个问题(https://github.com/sequelize/sequelize/issues/7525),我的代码中使用了 async,但是缺少了一个 await。 - The Coder
3
对我来说,forEach() 导致事务自动提交。在 forEach() 中我有一个异步方法。有人能解释一下吗? - nonNumericalFloat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接