transaction-interceptor.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
  2. import { Reflector } from '@nestjs/core';
  3. import { Observable, of } from 'rxjs';
  4. import { RequestContext } from '..';
  5. import { REQUEST_CONTEXT_KEY, REQUEST_CONTEXT_MAP_KEY } from '../../common/constants';
  6. import { TransactionWrapper } from '../../connection/transaction-wrapper';
  7. import { TransactionalConnection } from '../../connection/transactional-connection';
  8. import { parseContext } from '../common/parse-context';
  9. import { TransactionMode, TRANSACTION_MODE_METADATA_KEY } from '../decorators/transaction.decorator';
  10. /**
  11. * @description
  12. * Used by the {@link Transaction} decorator to create a transactional query runner
  13. * and attach it to the RequestContext.
  14. */
  15. @Injectable()
  16. export class TransactionInterceptor implements NestInterceptor {
  17. constructor(
  18. private connection: TransactionalConnection,
  19. private transactionWrapper: TransactionWrapper,
  20. private reflector: Reflector,
  21. ) {}
  22. intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
  23. const { isGraphQL, req } = parseContext(context);
  24. const ctx: RequestContext | undefined = (req as any)[REQUEST_CONTEXT_KEY];
  25. if (ctx) {
  26. const transactionMode = this.reflector.get<TransactionMode>(
  27. TRANSACTION_MODE_METADATA_KEY,
  28. context.getHandler(),
  29. );
  30. return of(
  31. this.transactionWrapper.executeInTransaction(
  32. ctx,
  33. _ctx => {
  34. this.registerTransactionalContext(_ctx, context.getHandler(), req);
  35. return next.handle();
  36. },
  37. transactionMode,
  38. this.connection.rawConnection,
  39. ),
  40. );
  41. } else {
  42. return next.handle();
  43. }
  44. }
  45. /**
  46. * Registers transactional request context associated with execution handler function
  47. *
  48. * @param ctx transactional request context
  49. * @param handler handler function from ExecutionContext
  50. * @param req Request object
  51. */
  52. // eslint-disable-next-line @typescript-eslint/ban-types
  53. registerTransactionalContext(ctx: RequestContext, handler: Function, req: any) {
  54. // eslint-disable-next-line @typescript-eslint/ban-types
  55. const map: Map<Function, RequestContext> = req[REQUEST_CONTEXT_MAP_KEY] || new Map();
  56. map.set(handler, ctx);
  57. req[REQUEST_CONTEXT_MAP_KEY] = map;
  58. }
  59. }