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' } from 'typeorm'
export const ENTITY_MANAGER = 'ENTITY_MANAGER' export const ENTITY_MANAGER = 'ENTITY_MANAGER'
export const TRANSACTION_ID = 'TRANSACTION_ID'
export interface ITransactionManager { export interface ITransactionManager {
getEntityManager: () => EntityManager getEntityManager: () => EntityManager
@ -13,6 +14,15 @@ export interface ITransactionManager {
target: ObjectType<Entity> | EntitySchema<Entity> | string, target: ObjectType<Entity> | EntitySchema<Entity> | string,
) => Repository<Entity> ) => Repository<Entity>
isInTransaction: () => boolean isInTransaction: () => boolean
/**
* Start a new or reuse an existing transaction.
*/
doInTransaction: <T>( doInTransaction: <T>(
fn: (entityManager: EntityManager) => Promise<T>) => Promise<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 {Namespace} from 'cls-hooked'
import {ENTITY_MANAGER, ITransactionManager} from './ITransactionManager' import shortid from 'shortid'
import {
ENTITY_MANAGER, ITransactionManager, TRANSACTION_ID
} from './ITransactionManager'
import { import {
Connection, Connection,
EntityManager, EntityManager,
@ -34,25 +37,38 @@ export class TransactionManager implements ITransactionManager {
return !!this.ns.get(ENTITY_MANAGER) 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() const alreadyInTransaction = this.isInTransaction()
if (alreadyInTransaction) { if (alreadyInTransaction) {
return await fn(this.getEntityManager()) return await fn(this.getEntityManager())
} }
return this.getConnection().manager return this.doInNewTransaction(fn)
}
async doInNewTransaction<T>(fn: (em: EntityManager) => Promise<T>) {
return this.ns.runAndReturn(async () => {
this.setTransactionId(shortid())
try {
return await this.getConnection().manager
.transaction(async entityManager => { .transaction(async entityManager => {
this.setEntityManager(entityManager) this.setEntityManager(entityManager)
try { try {
return await fn(entityManager) return await fn(entityManager)
} finally { } finally {
if (!alreadyInTransaction) {
this.setEntityManager(undefined) this.setEntityManager(undefined)
} }
})
} finally {
this.setTransactionId(undefined)
} }
}) })
} }
protected setTransactionId(transactionId: string | undefined) {
this.ns.set(TRANSACTION_ID, transactionId)
}
protected setEntityManager(entityManager: EntityManager | undefined) { protected setEntityManager(entityManager: EntityManager | undefined) {
this.ns.set(ENTITY_MANAGER, entityManager) this.ns.set(ENTITY_MANAGER, entityManager)
} }