-
Type: Bug
-
Resolution: Works as Designed
-
Priority: Unknown
-
None
-
Affects Version/s: None
-
Component/s: Performance
When running the driver and connecting to a database in node v20, the following error occurs:
TypeError: Cannot read properties of undefined (reading 'now') at new Timeout (/path/to/project/node_modules/.pnpm/mongodb@6.7.0_socks@2.8.3/node_modules/mongodb/src/timeout.ts:58:41) at Function.expires (/path/to/project/node_modules/.pnpm/mongodb@6.7.0_socks@2.8.3/node_modules/mongodb/src/timeout.ts:82:12) at Topology.selectServer (/path/to/project/node_modules/.pnpm/mongodb@6.7.0_socks@2.8.3/node_modules/mongodb/src/sdam/topology.ts:585:29) at Topology._connect (/path/to/project/node_modules/.pnpm/mongodb@6.7.0_socks@2.8.3/node_modules/mongodb/src/sdam/topology.ts:463:33) at Topology.connect (/path/to/project/node_modules/.pnpm/mongodb@6.7.0_socks@2.8.3/node_modules/mongodb/src/sdam/topology.ts:408:34) at topologyConnect (/path/to/project/node_modules/.pnpm/mongodb@6.7.0_socks@2.8.3/node_modules/mongodb/src/mongo_client.ts:554:30) at MongoClient._connect (/path/to/project/node_modules/.pnpm/mongodb@6.7.0_socks@2.8.3/node_modules/mongodb/src/mongo_client.ts:566:13) at MongoClient.connect (/path/to/project/node_modules/.pnpm/mongodb@6.7.0_socks@2.8.3/node_modules/mongodb/src/mongo_client.ts:477:34) at NativeConnection.createClient (/path/to/project/node_modules/.pnpm/mongoose@8.5.3_socks@2.8.3/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js:314:16) at NativeConnection.openUri (/path/to/project/node_modules/.pnpm/mongoose@8.5.3_socks@2.8.3/node_modules/mongoose/lib/connection.js:823:34) at Mongoose.Object.<anonymous>.Mongoose.createConnection (/path/to/project/node_modules/.pnpm/mongoose@8.5.3_socks@2.8.3/node_modules/mongoose/lib/mongoose.js:389:10) at Function.createMongooseConnection (/path/to/project/node_modules/.pnpm/@nestjs+mongoose@10.0.10_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_b7e7azbc32kdk3npgmil5pjkwi/node_modules/@nestjs/mongoose/dist/mongoose-core.module.js:114:37) at /path/to/project/node_modules/.pnpm/@nestjs+mongoose@10.0.10_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_b7e7azbc32kdk3npgmil5pjkwi/node_modules/@nestjs/mongoose/dist/mongoose-core.module.js:65:123 at Observable._subscribe (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/observable/defer.ts:55:15) at Observable.Object.<anonymous>.Observable._trySubscribe (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/Observable.ts:244:19) at /path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/Observable.ts:234:18 at Object.errorContext (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/util/errorContext.ts:29:5) at Observable.Object.<anonymous>.Observable.subscribe (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/Observable.ts:220:5) at subscribeForRetryWhen (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/operators/retryWhen.ts:74:25) at /path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/operators/retryWhen.ts:111:5 at OperatorSubscriber.<anonymous> (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/util/lift.ts:24:18) at /path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/Observable.ts:226:22 at Object.errorContext (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/util/errorContext.ts:29:5) at Observable.Object.<anonymous>.Observable.subscribe (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/Observable.ts:220:5) at /path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/operators/catchError.ts:115:23 at SafeSubscriber.<anonymous> (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/util/lift.ts:24:18) at /path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/Observable.ts:226:22 at Object.errorContext (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/util/errorContext.ts:29:5) at Observable.Object.<anonymous>.Observable.subscribe (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/Observable.ts:220:5) at /path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/lastValueFrom.ts:59:12 at new Promise (<anonymous>) at lastValueFrom (/path/to/project/node_modules/.pnpm/rxjs@7.8.1/node_modules/rxjs/src/internal/lastValueFrom.ts:56:10) at InstanceWrapper.useFactory [as metatype] (/path/to/project/node_modules/.pnpm/@nestjs+mongoose@10.0.10_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_b7e7azbc32kdk3npgmil5pjkwi/node_modules/@nestjs/mongoose/dist/mongoose-core.module.js:65:55) at TestingInjector.instantiateClass (/path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/injector.js:368:55) at callback (/path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/injector.js:65:45) at processTicksAndRejections (node:internal/process/task_queues:95:5) at TestingInjector.resolveConstructorParams (/path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/injector.js:144:24) at TestingInjector.loadInstance (/path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/injector.js:70:13) at TestingInjector.loadProvider (/path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/injector.js:97:9) at /path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/instance-loader.js:56:13 at async Promise.all (index 4) at TestingInstanceLoader.createInstancesOfProviders (/path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/instance-loader.js:55:9) at /path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/instance-loader.js:40:13 at async Promise.all (index 9) form/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/instance-loader.js:39:9) at TestingInstanceLoader.createInstancesOfDependencies (/path/to/project/node_modules/.pnpm/@nestjs+core@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_refl_cm7eoljwmhxzk4jjou7u2pgemq/node_modules/@nestjs/core/injector/instance-loader.js:22:13) at TestingInstanceLoader.createInstancesOfDependencies (/path/to/project/node_modules/.pnpm/@nestjs+testing@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_r_4fkxwolokzjrsak3izk6eol6ga/node_modules/@nestjs/testing/testing-instance-loader.js:9:9) at TestingModuleBuilder.createInstancesOfDependencies (/path/to/project/node_modules/.pnpm/@nestjs+testing@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_r_4fkxwolokzjrsak3izk6eol6ga/node_modules/@nestjs/testing/testing-module.builder.js:118:9) at TestingModuleBuilder.compile (/path/to/project/node_modules/.pnpm/@nestjs+testing@10.3.8_@nestjs+common@10.3.8_class-transformer@0.5.1_class-validator@0.14.0_r_4fkxwolokzjrsak3izk6eol6ga/node_modules/@nestjs/testing/testing-module.builder.js:74:9)
The fix appears to be to import performance from the perf_hooks package for better compatibility in different versions of Node.js as in this patch:
diff --git a/lib/timeout.js b/lib/timeout.jsindex 758aeef9f54a5f1c31b4aa75945374b34e904ee3..40970fa4af4836b351434249012c2c7668843446 100644--- a/lib/timeout.js+++ b/lib/timeout.js@@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Timeout = exports.TimeoutError = void 0;+const performance_1 = require("perf_hooks"); const timers_1 = require("timers"); const error_1 = require("./error"); const utils_1 = require("./utils");@@ -40,10 +41,10 @@ class Timeout extends Promise { this.ended = null; this.timedOut = false; this.duration = duration;- this.start = Math.trunc(performance.now());+ this.start = Math.trunc(performance_1.performance.now()); if (this.duration > 0) { this.id = (0, timers_1.setTimeout)(() => {- this.ended = Math.trunc(performance.now());+ this.ended = Math.trunc(performance_1.performance.now()); this.timedOut = true; reject(new TimeoutError(`Expired after ${duration}ms`)); }, this.duration);diff --git a/src/timeout.ts b/src/timeout.tsindex 7d0af2383d3ec2860da9550db7183b7b1f6dd08f..433ee081bf7fdc895ec69bf93a042320dc4e9798 100644--- a/src/timeout.ts+++ b/src/timeout.ts@@ -1,3 +1,4 @@+import { performance } from 'perf_hooks'; import { clearTimeout, setTimeout } from 'timers'; import { MongoInvalidArgumentError } from './error';
Use Case
As a user using v20 of Node.js
I want my app not to crash when I use the mongodb node driver
So that my app can function properly
User Experience
- What is the desired/expected outcome for the user once this ticket is implemented?
- A bug fix is released
- If bug: What is the number of impacted customers? How severe is the impact? Is anyone blocked or broken?
- I would imagine anyone using node v20 or lower
Dependencies
- Mongoose v8.5.3 (latest version as of this writing) has mongodb pinned at v6.7.0. We'll need to work with them bring in the latest version of mongodb
Risks/Unknowns
- What could go wrong while implementing this change? (e.g., performance, inadvertent behavioral changes in adjacent functionality, existing tech debt, etc)
- It feels like a fairly low risk change, just need to test this with all supported versions of Node.js
- Is there an opportunity for better cross-driver alignment or testing in this area?
- :shrug:
- Is there an opportunity to improve existing documentation on this subject?
- No new documentation should be required as far as I know...
Acceptance Criteria
Implementation Requirements
- functional reqs, potential snafus to avoid, performance targets, etc
Testing Requirements
- unit test, spec test sync, etc
Documentation Requirements
- DOCSP ticket, API docs, etc
Follow Up Requirements
- additional tickets to file, required releases, etc
- if node behavior differs/will differ from other drivers, confirm with dbx devs what standard to aim for and what plan, if any, exists to reconcile the diverging behavior moving forward