transaction-plugin.ts 1.7 KB

123456789101112131415161718192021222324252627282930313233343536
  1. import { ApolloServerPlugin, GraphQLRequestListener, GraphQLServiceContext } from 'apollo-server-plugin-base';
  2. import { EntityManager } from 'typeorm';
  3. import { REQUEST_CONTEXT_KEY, TRANSACTION_MANAGER_KEY } from '../../common/constants';
  4. import { AssetStorageStrategy } from '../../config/asset-storage-strategy/asset-storage-strategy';
  5. import { TransactionalConnection } from '../../service/transaction/transactional-connection';
  6. import { RequestContext } from '../common/request-context';
  7. /**
  8. * @description
  9. * Intercepts outgoing responses to see if there is an open QueryRunner attached to the
  10. * RequestContext. This is necessary when using the {@link TransactionInterceptor} because
  11. * it opens a transaction without releasing it.
  12. *
  13. * The reason that the `.release()` call is done here, and not in a `finally` block
  14. * in the TransactionInterceptor is that this plugin runs after _all nested resolvers_
  15. * have resolved, whereas the Interceptor considers the request complete after only the
  16. * top-level resolver returns.
  17. */
  18. export class TransactionPlugin implements ApolloServerPlugin {
  19. requestDidStart(): GraphQLRequestListener {
  20. return {
  21. willSendResponse: async requestContext => {
  22. const { context } = requestContext;
  23. const transactionManager: EntityManager | undefined =
  24. context.req?.[REQUEST_CONTEXT_KEY]?.[TRANSACTION_MANAGER_KEY];
  25. if (transactionManager) {
  26. const { queryRunner } = transactionManager;
  27. if (queryRunner?.isReleased === false) {
  28. await queryRunner.release();
  29. }
  30. }
  31. },
  32. };
  33. }
  34. }