shelfio / jest-mongodb

Jest preset for MongoDB in-memory server
MIT License
587 stars 83 forks source link

MongoWriteConcernError: operation was interrupted #463

Open luispellizzon opened 1 month ago

luispellizzon commented 1 month ago

So I am working on a project where I needed use a Replica Set because of MongoDb Transactions, and up to yesterday I did not need transactions on the project I am working on, but started getting errors on jest tests.

All previous unit and integration tests were passing successfully, but after implementing a transaction in a TransactionManager interface and test it, it starts breaking other tests even tho they are not related with the transactions, but with MongoDb instance.

On previous tests that required all that jest mongo connection template to test, it was working fine:

 let accountsCollection: Collection
  beforeAll(async () => {
    await MongoHelper.connect(process.env.MONGO_URL)
  })
  afterAll(async () => {
    await MongoHelper.disconnect()
  })

  beforeEach(async () => {
    accountsCollection = await MongoHelper.getCollection('accounts')
    await accountsCollection.deleteMany({})
  })

Here is the error:

MongoWriteConcernError: operation was interrupted

But then, after implementing one transaction, it all tests only works if I start cleaning the collection used (by any test) on afterEach method, and instantiating the collection on beforeAll method, like the following:

  beforeAll(async () => {
    await MongoHelper.connect(process.env.MONGO_URL)
    accountsCollection = await MongoHelper.getCollection('accounts')
  })
  afterAll(async () => {
    await MongoHelper.disconnect()
  })

  afterEach(async () => {
    await accountsCollection.deleteMany({})
  })

Here is the TransactionManager interface implemented:

import { TransactionManager } from '@/data/protocols/transaction/transaction-manager'
import { MongoHelper } from '../helpers/mongo-helper'
import { ClientSession } from 'mongodb'

export class MongoDbTransactionManager implements TransactionManager {
  async executeTransaction<T> (transaction: (session?: ClientSession) => Promise<T>): Promise<T> {
    const session = MongoHelper.client.startSession()
    try {
      const result = await session.withTransaction(async () => await transaction(session), {
        readPreference: 'primary',
        retryWrites: true,
        readConcern: { level: 'local' },
        writeConcern: { w: 'majority' }
      })
      return result
    } finally {
      await session.endSession()
    }
  }
}

NOTE

This transaction is only used in one use case not related to all other tests on the project, but it seems that this is breaking something on MongoDbMemoryServer which is instantiated, but by changing to clean every collection used in a test AFTER each test then all tests works magically.