Sequelize:交易的不同处理

5 sql t-sql node.js sequelize.js

假设我们已经使用 Sequelize 模型实现了几个(虚拟)服务来访问我们的数据库:

export class AService {
    // ... some other stuff
    async updateSomeA(aId: number, value: string) {

        let instanceA = await ModelA.findById(aId);

        // need this update to use the transaction!
        await instanceA.update({
            some_field: value
        });
    }

}

export class BService {
    // ... some other stuff
    async updateB(bId: number, value: string) {

        let instanceB = await ModelB.findById(bId);

        // and this one as well!
        await instanceB.update({
            some_field_in_b: value
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们想从代码中的其他地方(比如 from )调用updateSomeAand ,但我们希望这些调用包含在事务中。updateBCService

class CService {

    // ...stuff

    async f() {

        // == begin transaction
        await AService.updateSomeA(1, 'blah!');
        await BService.updateB(3, 'meh');
        // == end transaction
    }
}
Run Code Online (Sandbox Code Playgroud)

根据我通过文档收集的信息,为了通过事务保护代码,我需要将其包装在回调中或使用承诺。是对的吗?

如果是这样的话,那么我将被迫修改我的服务,并且可能有一些“支持交易”的方法版本,对吗?

你们知道是否有计划支持类似的事情

Transaction.begin("myAwesomeTransaction");

// ... every SQL generated in here is 'safe'

Transaction.end();
Run Code Online (Sandbox Code Playgroud)

编辑:“交易作为参数”解决方案

当然,我们总是可以将交易作为所有服务函数中可选的最后一个参数,或者至少是具有副作用的服务函数(即deleteAupdateB, 等)。就像是:

// ... changed AService.updateSomeA
async updateSomeA(aId: number, value: string, t?: Sequelize.Transaction) {

    let instanceA = await ModelA.findById(aId);
    await instanceA.update({
        some_field: value
    }, {
        transaction: t  // we use the transaction if we get one
    });
}
Run Code Online (Sandbox Code Playgroud)

但是我们的呢CService.f()?该函数应该创建交易并将其传递下来,还是期望交易作为可选参数?嗯,答案是两者兼而有之,不是吗?如果我们f()从其他服务调用作为较大事务的一部分,我们希望它接收该Transaction实例并使用它。另一方面,如果我们f()外部(例如控制器)调用,我们不想在那里创建事务......对吗?!

所以,我们最终得到这样的结果:

// ... changed CService.f
async f(t?: Sequelize.Transaction) {

    if(!t) return sequelize.transaction(_f); // using the autoCallback overload
    else return _f(t);

    async function _f(trans: Sequelize.Transaction) {

        // ... actual code for f() goes here
    }
}
Run Code Online (Sandbox Code Playgroud)

完美的?不……期待您的意见!