sequelize-transactional
Version:
A Transactional method decorator for Sequelize
126 lines (95 loc) ⢠3.38 kB
Markdown
# sequelize-transactional
A `Transactional` method decorator for sequelize that uses cls-hooked to handle and propagate transactions between different service methods.
ā
This package is very suitable for use with NestJS.
## Installation
```shell
yarn add sequelize-transactional
# or
npm install sequelize-transactional --save
```
## Usage
### _Step 1_
**Before establishing any connections** using Sequelize,
you need to enable Sequelize to use node CLS:
```typescript
import { initSequelizeCLS } from 'sequelize-transactional';
initSequelizeCLS();
```
In NesJS you can call this in the main.ts after the app declaration.
### _Step 2_
### If you use sequelize in your NestJS app:
Import `SequelizeTransactionalModule.register()` into your root application module.
Example:
```typescript
@Module({
imports: [
SequelizeModule.forRoot({
...
}),
SequelizeTransactionalModule.register(),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
```
If you specified custom connection name in `SequelizeModule`, pass `connectionName` into options:
```typescript
@Module({
imports: [
SequelizeModule.forRoot({
...
name: 'my-connection-name',
}),
SequelizeTransactionalModule.register({ connectionName: 'my-connection-name' }),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
```
### If you don't use NestJS
Just call _initSequelizeTransactional_ after establishing a connection:
```typescript
const sequelize = new Sequelize({ ... })
initSequelizeTransactional(sequelize) // pass your Sequelize conection here
```
### Step 3
Use `Transactional` annotation on your class methods.
Example:
```typescript
@Injectable()
export class AppService {
constructor(
@InjectModel(Something)
private readonly something: typeof Something,
private readonly anotherService: AnotherService,
) {}
@Transactional()
async appMethod(): Promise<void> {
await this.something.create({ message: 'hello' });
await this.something.create({ message: 'world' });
await this.anotherService.method(); // other service's method will use the same transaction
}
}
```
`@Transactional` decorator accepts `options` object:
```typescript
{
isolationLevel?: string; // Isolation Level of transaction. Default value depends on your Sequelize config or the database you use
propagation?: string; // Default value is REQUIRED. Allowed options are described below
}
```
## Propagation options
- `REQUIRED` (default) - If exists, use current transaction, otherwise create a new one.
- `SUPPORTS` - If exists, use current transaction, otherwise execute without transaction.
- `MANDATORY` - If exists, use current transaction, otherwise throw an exception.
- `NEVER` - Execute without transaction. If an active transaction exists, throw an exception.
- `NOT_SUPPORTED` - Execute without transaction, suspend an active transaction if it exists.
- `REQUIRES_NEW` - Always execute in a separate transaction, suspend an active transaction if it exists.
## Isolation Level Options
- `READ UNCOMMITTED`
- `READ COMMITTED`
- `REPEATABLE READ`
- `SERIALIZABLE`
For more info refer to your database documentation.