Papooch / nestjs-cls

A continuation-local storage (async context) module compatible with NestJS's dependency injection.
https://papooch.github.io/nestjs-cls/
MIT License
389 stars 23 forks source link

Add support for nesting @Transactional decorators #108

Closed kareemalkoul closed 5 months ago

kareemalkoul commented 5 months ago

i use function used @Transactional inside this function calling to function using aleady @Transactional, so i noticed the parent @Transactional is ovveride dont use it so it is act like not @Transactional in parent function ex:

 @Transactional()
async parentfun(){

   await fun1()
   await fun2()
}

@Transactional()
async fun1(){

    //some operation from prisma

}

@Transactional()
async fun2(){

    //some operation from prisma

}

in the example above if some error happen in fun2 the operation in fun1 not rollback

Papooch commented 5 months ago

Yes, that is true. Currently, each @Transactional decorator creates a new transaction.

I have a plan to add nesting options soon, but for now it's a limitation of the library, so please stay tuned.

Papooch commented 5 months ago

I propose the following APIs for the propagation control, inspired by the Spring framework:

An enum called Propagation with possible values:

Introducing the default behavior or Propagation.Required wold be a BREAKING CHANGE since the default (and only mode) is now Propagation.RequiresNew

And then use it in one of the following ways (TO BE DECIDED) to specify it:

1) Pass it as the first parameter to the @Transactional or withTransaction calls

@Transactional(Propagation.RequiresNew, { someAdapterOption: ... })
async doSomething(){
  // ...
}

async doSomething(){
  return this.txHost.withTransaction(Propagation.RequiresNew, { someAdapterOption: ... }, async () => {
    // ...
  })
}

2) ~Mix it into the adapter options~

@Transactional({
  propagation: Propagation.RequiresNew,
  someAdapterOption: ...
})
async doSomething(){
  // ...
}

async doSomething(){
  return this.txHost.withTransaction({
    propagation: Propagation.RequiresNew,
    someAdapterOption: ... 
  }, async () => {
    // ...
  })
}

3) ~Move adapter options into a nested field instead~

async doSomething(){ return this.txHost.withTransaction({ propagation: Propagation.RequiresNew, adapterOptions: { someAdapterOption: ... } }, async () => { // ... }) }

Papooch commented 5 months ago

@kareemalkoul An update with a support for propagation modes was just published, please update @nestjs-cls/transactional to v2 and your adapter to latest and see the new documentation.

npm i @nestjs-cls/transactional@latest @nestjs-cls/transactional-adapter-<youradapter>@latest