Add TransactionManager.doInNewTransaction

This commit is contained in:
Jerko Steiner 2019-08-26 19:07:21 +07:00
parent 67ae8dac57
commit 02d072a361
2 changed files with 35 additions and 9 deletions

View File

@ -6,6 +6,7 @@ import {
} from 'typeorm'
export const ENTITY_MANAGER = 'ENTITY_MANAGER'
export const TRANSACTION_ID = 'TRANSACTION_ID'
export interface ITransactionManager {
getEntityManager: () => EntityManager
@ -13,6 +14,15 @@ export interface ITransactionManager {
target: ObjectType<Entity> | EntitySchema<Entity> | string,
) => Repository<Entity>
isInTransaction: () => boolean
/**
* Start a new or reuse an existing transaction.
*/
doInTransaction: <T>(
fn: (entityManager: EntityManager) => Promise<T>) => Promise<T>
/**
* Always start a new transaction, regardless if there is one already in
* progress in the current context.
*/
doInNewTransaction: <T>(
fn: (entityManager: EntityManager) => Promise<T>) => Promise<T>
}

View File

@ -1,5 +1,8 @@
import {Namespace} from 'cls-hooked'
import {ENTITY_MANAGER, ITransactionManager} from './ITransactionManager'
import shortid from 'shortid'
import {
ENTITY_MANAGER, ITransactionManager, TRANSACTION_ID
} from './ITransactionManager'
import {
Connection,
EntityManager,
@ -34,25 +37,38 @@ export class TransactionManager implements ITransactionManager {
return !!this.ns.get(ENTITY_MANAGER)
}
async doInTransaction<T>(fn: (entityManager: EntityManager) => Promise<T>) {
async doInTransaction<T>(fn: (em: EntityManager) => Promise<T>) {
const alreadyInTransaction = this.isInTransaction()
if (alreadyInTransaction) {
return await fn(this.getEntityManager())
}
return this.getConnection().manager
.transaction(async entityManager => {
this.setEntityManager(entityManager)
return this.doInNewTransaction(fn)
}
async doInNewTransaction<T>(fn: (em: EntityManager) => Promise<T>) {
return this.ns.runAndReturn(async () => {
this.setTransactionId(shortid())
try {
return await fn(entityManager)
return await this.getConnection().manager
.transaction(async entityManager => {
this.setEntityManager(entityManager)
try {
return await fn(entityManager)
} finally {
this.setEntityManager(undefined)
}
})
} finally {
if (!alreadyInTransaction) {
this.setEntityManager(undefined)
}
this.setTransactionId(undefined)
}
})
}
protected setTransactionId(transactionId: string | undefined) {
this.ns.set(TRANSACTION_ID, transactionId)
}
protected setEntityManager(entityManager: EntityManager | undefined) {
this.ns.set(ENTITY_MANAGER, entityManager)
}