Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AsyncLocalStorage driver #39

Merged
merged 16 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
name: main
on: [push]

jobs:
main:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
version: ['12.x', '18.x', '20.x']
storageDriver: ['ASYNC_LOCAL_STORAGE', 'CLS_HOOKED']
steps:
- uses: actions/checkout@v2

- name: Check If Tag
id: check-tag
run: |-
if [[ ${{ github.event.ref }} =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo ::set-output name=match::true
fi
- uses: actions/checkout@v4

- uses: actions/setup-node@v1
- uses: actions/setup-node@v3
with:
node-version: '12.x'
node-version: ${{ matrix.version }}
registry-url: 'https://registry.npmjs.org'

- name: Install
run: npm install

- name: Test
run: npm test
env:
TEST_STORAGE_DRIVER: ${{ matrix.storageDriver }}

publish:
if: startsWith(github.event.ref, 'refs/tags/v')
needs: tests
runs-on: ubuntu-latest
steps:
- name: Install
run: npm install

- name: Build
run: npm run build

- name: Publish
if: steps.check-tag.outputs.match == 'true'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}


40 changes: 30 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
## It's a fork of [typeorm-transactional-cls-hooked](https://github.com/odavid/typeorm-transactional-cls-hooked) for new versions of TypeORM.


A `Transactional` Method Decorator for [typeorm](http://typeorm.io/) that uses [cls-hooked](https://www.npmjs.com/package/cls-hooked) to handle and propagate transactions between different repositories and service methods.
A `Transactional` Method Decorator for [typeorm](http://typeorm.io/) that uses [ALS](https://nodejs.org/api/async_context.html#class-asynclocalstorage) or [cls-hooked](https://www.npmjs.com/package/cls-hooked) to handle and propagate transactions between different repositories and service methods.

See [Changelog](#CHANGELOG.md)

Expand All @@ -23,9 +23,10 @@ See [Changelog](#CHANGELOG.md)
- [API](#api)
- [Library Options](#library-options)
- [Transaction Options](#transaction-options)
- [initializeTransactionalContext(options): void](#initializetransactionalcontext-void)
- [Storage Driver](#storage-driver)
- [initializeTransactionalContext(options): void](#initializetransactionalcontextoptions-void)
- [addTransactionalDataSource(input): DataSource](#addtransactionaldatasourceinput-datasource)
- [runInTransaction(fn: Callback, options?: Options): Promise<...>](#runintransactionfn-callback-options-options-promise)
- [runInTransaction(fn: Callback, options?: Options): Promise\<...\>](#runintransactionfn-callback-options-options-promise)
- [wrapInTransaction(fn: Callback, options?: Options): WrappedFunction](#wrapintransactionfn-callback-options-options-wrappedfunction)
- [runOnTransactionCommit(cb: Callback): void](#runontransactioncommitcb-callback-void)
- [runOnTransactionRollback(cb: Callback): void](#runontransactionrollbackcb-callback-void)
Expand Down Expand Up @@ -53,12 +54,12 @@ yarn add typeorm reflect-metadata

## Initialization

In order to use it, you will first need to initialize the cls-hooked namespace before your application is started
In order to use it, you will first need to initialize the transactional context before your application is started

```typescript
import { initializeTransactionalContext } from 'typeorm-transactional';

initializeTransactionalContext() // Initialize cls-hooked
initializeTransactionalContext()
...
app = express()
...
Expand All @@ -77,7 +78,7 @@ To be able to use TypeORM entities in transactions, you must first add a DataSou

```typescript
import { DataSource } from 'typeorm';
import { initializeTransactionalContext, addTransactionalDataSource } from 'typeorm-transactional';
import { initializeTransactionalContext, addTransactionalDataSource, StorageDriver } from 'typeorm-transactional';
...
const dataSource = new DataSource({
type: 'postgres',
Expand All @@ -88,7 +89,7 @@ const dataSource = new DataSource({
});
...

initializeTransactionalContext();
initializeTransactionalContext({ storageDriver: StorageDriver.ASYNC_LOCAL_STORAGE });
addTransactionalDataSource(dataSource);

...
Expand Down Expand Up @@ -298,10 +299,11 @@ Repositories, services, etc. can be mocked as usual.

```typescript
{
storageDriver?: StorageDriver,
maxHookHandlers?: number
}
```

- `storageDriver` - Determines which [underlying mechanism](#storage-driver) (like Async Local Storage or cls-hooked) the library should use for handling and propagating transactions. By default, it's `StorageDriver.CLS_HOOKED`.
- `maxHookHandlers` - Controls how many hooks (`commit`, `rollback`, `complete`) can be used simultaneously. If you exceed the number of hooks of same type, you get a warning. This is a useful to find possible memory leaks. You can set this options to `0` or `Infinity` to indicate an unlimited number of listeners. By default, it's `10`.

### Transaction Options
Expand All @@ -314,13 +316,31 @@ Repositories, services, etc. can be mocked as usual.
}
```

- `connectionName`- DataSource` name to use for this transactional context ([the data sources](#data-sources))
- `connectionName`- DataSource name to use for this transactional context ([the data sources](#data-sources))
- `isolationLevel`- isolation level for transactional context ([isolation levels](#isolation-levels) )
- `propagation`- propagation behaviors for nest transactional contexts ([propagation behaviors](#transaction-propagation))

### Storage Driver

Option that determines which underlying mechanism the library should use for handling and propagating transactions.

The possible variants:

- `AUTO` - Automatically selects the appropriate storage mechanism based on the Node.js version, using `AsyncLocalStorage` for Node.js versions 16 and above, and defaulting to `cls-hooked` for earlier versions.
- `CLS_HOOKED` - Utilizes the `cls-hooked` package to provide context storage, supporting both legacy Node.js versions with AsyncWrap for versions below 8.2.1, and using `async_hooks` for later versions.
- `ASYNC_LOCAL_STORAGE` - Uses the built-in `AsyncLocalStorage` feature, available from Node.js version 16 onwards,

> ⚠️ **WARNING:** Currently, we use `CLS_HOOKED` by default for backward compatibility. However, in the next major release, this default will be switched to `AUTO`.

```typescript
import { StorageDriver } from 'typeorm-transactional'

initializeTransactionalContext({ storageDriver: StorageDriver.AUTO });
```

### initializeTransactionalContext(options): void

Initialize `cls-hooked` namespace.
Initialize transactional context.

```typescript
initializeTransactionalContext(options?: TypeormTransactionalOptions);
Expand Down
Loading