postgresql 如何 Package 在事务中使用事务的代码,然后回滚?

vc6uscn9  于 2022-11-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(256)

bounty将在17小时后过期。回答此问题可获得+50声望奖励。Jen希望吸引更多人关注此问题。

我正在设置我的集成测试平台。我正在使用beforeEachafterEach钩子来 Package 回滚事务中的每一个测试,以便测试不会相互影响。一个简化的示例如下:

const { repository } = require("library")

describe("Suite", function () {
  beforeEach(async function () {
    await knex.raw("BEGIN");
  });

  afterEach(async function () {
    await knex.raw("ROLLBACK");
  });

  it("A test", async function () {
    const user = await repository.createUser()
    user.id.should.equal(1)
  });
});

这样做很好,因为我将knex配置为使用单个DB连接进行测试,因此调用knex.raw("BEGIN");创建了一个 global 事务。
但是现在,我无法控制的库的仓库开始在内部使用事务。即createUser()开始,然后 * commit * 创建的用户。这破坏了我的测试,因为现在我的afterEach钩子不回滚更改,因为它们已经被提交了。
Postgres中是否有方法回滚具有(已提交)嵌套事务的事务?
或者是一种使用knex的方法来防止存储库从一开始就启动事务?它使用knex.transaction()来创建事务。
谢谢你!

fivyi3re

fivyi3re1#

从示例调试日志的外观来看,knex实际上确实自动检测事务嵌套,并将嵌套事务从使用不可逆的commit/rollback切换到manageablesavepoint s1/release s1/rollback to s1,正如我在评论中猜测的那样。
在这种情况下,您只需将调用 Package 在一个事务中,这样您就“拥有”了顶层事务。Knex应该检测到这一点,并强制底层事务使用保存点而不是提交,然后您可以撤消所有这些操作,回滚顶层事务。如果我没有看错the doc

const { repository } = require("library")
 
describe("Suite", function () {
  it("A test", async function () {
    try {
        await knex.transaction(async trx => {
          const user = await repository.createUser();
          user.id.should.equal(1);
          trx.rollback();
        })
    } catch (error) {
      console.error(error);
    }
  });
});

这是假设下面的调用都没有发出knex.raw("ROLLBACK")或以某种方式调用外部顶级事务上的.rollback()

相关问题