mongodb-memory-server: "getport" sometimes throwing an error

Versions

  • NodeJS: 16.20.2
  • mongodb-memory-server-*: 9.0.1
  • mongodb(the binary version): 6.0.10
  • mongodb(the js package): 5.9.0
  • system: MacOS 14.1

package: mongo-memory-server

What is the Problem?

When I’m trun to run test using “vitest@0.34.6” in concurrency mode I have an error that port already in use. No always, but pretty often

Starting the MongoMemoryServer Instance failed, enable debug log for more information. Error:
 StdoutInstanceError: Port "15490" already in use

Want to notice that there is no error on v8.16.0

Code Example

globalThis.__MONGO_DB__ = await MongoMemoryServer.create();

Debug Output

stderr | unknown test
Starting the MongoMemoryServer Instance failed, enable debug log for more information. Error:
 StdoutInstanceError: Port "52929" already in use
    at MongoInstance.checkErrorInLine (/.../node_modules/.pnpm/mongodb-memory-server-core@9.0.1/node_modules/mongodb-memory-server-core/src/util/MongoInstance.ts:641:9)
    at MongoInstance.stdoutHandler (/.../node_modules/.pnpm/mongodb-memory-server-core@9.0.1/node_modules/mongodb-memory-server-core/src/util/MongoInstance.ts:615:10)
    at Socket.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at Socket.Readable.push (node:internal/streams/readable:228:10)
    at Pipe.onStreamRead (node:internal/stream_base_commons:190:23)

Do you know why it happenes?

Looks like there is a race condition after replacing “get-port” to own implementation

About this issue

  • Original URL
  • State: open
  • Created 8 months ago
  • Reactions: 3
  • Comments: 41

Commits related to this issue

Most upvoted comments

version 9.1.5 has been released with #844, which at least fixes the use of Date.now() as a starting port (and instead uses crypto.randomInt)

Marking the Issue as stale, it will be closed in 7 days if no more activity is seen

In our case, the problem comes from mocked dates in Jest.

We have this in the Jest setup file:

const jestDateMock = require('jest-date-mock');
jestDateMock.advanceTo(new Date('2020-07-01T00:00:00Z'));

Since mongodb-memory-server-core uses Date.now() as a source of randomness, firstPort now always resolves with the same port number, and we always get Port "22815" already in use.

https://github.com/nodkz/mongodb-memory-server/blob/master/packages/mongodb-memory-server-core/src/util/getport/index.ts#L52

Possible solutions:

  • stop relying on Date.now for randomness and instead do smth like Math.random?
  • if you are keen on using timestamps, maybe use process.hrtime.bigint() instead, as mocking Date in Jest should be very common?

Workaround

For now this workaround helped us fix the issue:

jestDateMock.clear();
await replSet.start();
jestDateMock.advanceTo(new Date('2020-07-01T00:00:00Z'));
Port "50113" already in use
  at MongoInstance.checkErrorInLine (node_modules/mongodb-memory-server-core/src/util/MongoInstance.ts:611:9)
  at MongoInstance.stdoutHandler (node_modules/mongodb-memory-server-core/src/util/MongoInstance.ts:585:10)

In the code referenced I think we need a lock of sorts for PORTS_CACHE. If we could await read and writing of that value. Does that sound about right?

We’ve had the same issue with v9.0.1 on macos and on GHA linux build machines, where v8.13.0 was fine.

We ended up with this workaround:

import getPort from 'get-port';
import retry from 'async-retry';

const port = await getPort();
const mongo = await retry(
  () =>
    MongoMemoryReplSet.create({
      ...this.testEnvironmentOptions,
      instanceOpts: [{ port }],
      replSet: { count: 2 },
    }),
  {
    retries: 3,
  },
);