Skip to content

Commit d3415ed

Browse files
committed
chore: fix more unhandling
1 parent 63aa846 commit d3415ed

File tree

7 files changed

+35
-24
lines changed

7 files changed

+35
-24
lines changed

src/sdam/server.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,8 +346,11 @@ export class Server extends TypedEventEmitter<ServerEvents> {
346346
operationError instanceof MongoError &&
347347
operationError.code === MONGODB_ERROR_CODES.Reauthenticate
348348
) {
349-
// TODO: what do we do with this error? the signal has aborted so where should it be delivered?
350-
reauthPromise = this.pool.reauthenticate(conn).then(undefined, squashError);
349+
reauthPromise = this.pool.reauthenticate(conn);
350+
reauthPromise.then(undefined, error => {
351+
reauthPromise = null;
352+
squashError(error);
353+
});
351354

352355
await abortable(reauthPromise, options);
353356
reauthPromise = null; // only reachable if reauth succeeds

src/sdam/topology.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -559,11 +559,6 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
559559
new ServerSelectionStartedEvent(selector, this.description, options.operationName)
560560
);
561561
}
562-
let timeout;
563-
if (options.timeoutContext) timeout = options.timeoutContext.serverSelectionTimeout;
564-
else {
565-
timeout = Timeout.expires(options.serverSelectionTimeoutMS ?? 0);
566-
}
567562

568563
const isSharded = this.description.type === TopologyType.Sharded;
569564
const session = options.session;
@@ -586,10 +581,16 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
586581
)
587582
);
588583
}
589-
if (options.timeoutContext?.clearServerSelectionTimeout) timeout?.clear();
584+
590585
return transaction.server;
591586
}
592587

588+
let timeout;
589+
if (options.timeoutContext) timeout = options.timeoutContext.serverSelectionTimeout;
590+
else {
591+
timeout = Timeout.expires(options.serverSelectionTimeoutMS ?? 0);
592+
}
593+
593594
const { promise: serverPromise, resolve, reject } = promiseWithResolvers<Server>();
594595

595596
const waitQueueMember: ServerSelectionRequest = {

src/timeout.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { clearTimeout, setTimeout } from 'timers';
33
import { type Document } from './bson';
44
import { MongoInvalidArgumentError, MongoOperationTimeoutError, MongoRuntimeError } from './error';
55
import { type ClientSession } from './sessions';
6-
import { csotMin, noop } from './utils';
6+
import { csotMin, noop, squashError } from './utils';
77

88
/** @internal */
99
export class TimeoutError extends Error {
@@ -102,7 +102,13 @@ export class Timeout extends Promise<never> {
102102
}
103103

104104
throwIfExpired(): void {
105-
if (this.timedOut) throw new TimeoutError('Timed out', { duration: this.duration });
105+
if (this.timedOut) {
106+
// This method is invoked when someone wants to throw immediately instead of await the result of this promise
107+
// Since they won't be handling the rejection from the promise (because we're about to throw here)
108+
// attach handling to prevent this from bubbling up to Node.js
109+
this.then(undefined, squashError);
110+
throw new TimeoutError('Timed out', { duration: this.duration });
111+
}
106112
}
107113

108114
public static expires(duration: number, unref?: true): Timeout {

test/integration/client-side-operations-timeout/node_csot.test.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,9 @@ describe('CSOT driver tests', metadata, () => {
10231023

10241024
beforeEach(async function () {
10251025
cs = client.db('db').collection('coll').watch([], { timeoutMS: 120 });
1026-
const _changePromise = once(cs, 'change');
1026+
const changePromise = once(cs, 'change');
1027+
void changePromise.then(undefined, () => null); // need to handled when this rejects with the timeout error
1028+
10271029
await once(cs.cursor, 'init');
10281030

10291031
await internalClient.db().admin().command(failpoint);

test/integration/node-specific/examples/change_streams.test.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
'use strict';
33

44
const { setTimeout } = require('timers');
5-
const setupDatabase = require('../../shared').setupDatabase;
65
const expect = require('chai').expect;
76

87
// TODO: NODE-3819: Unskip flaky MacOS/Windows tests.
@@ -11,13 +10,9 @@ maybeDescribe('examples(change-stream):', function () {
1110
let client;
1211
let db;
1312

14-
before(async function () {
15-
await setupDatabase(this.configuration);
16-
});
17-
1813
beforeEach(async function () {
1914
client = await this.configuration.newClient().connect();
20-
db = client.db(this.configuration.db);
15+
db = client.db('change_stream_examples');
2116

2217
// ensure database exists, we need this for 3.6
2318
await db.collection('inventory').insertOne({});
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
/* eslint-disable no-console */
12
// eslint-disable-next-line @typescript-eslint/no-require-imports
23
const process = require('process');
34

4-
process.on('unhandledRejection', error => {
5+
process.on('unhandledRejection', (error, promise) => {
6+
console.log('promise:', promise, 'unhandledRejection:', error);
57
throw error;
68
});

test/unit/cmap/auth/auth_provider.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ describe('AuthProvider', function () {
88
const provider = new AuthProvider();
99
const context = { reauthenticating: true };
1010

11-
it('returns an error', function () {
12-
provider.reauth(context, error => {
13-
expect(error).to.exist;
14-
expect(error).to.be.instanceOf(MongoRuntimeError);
15-
expect(error?.message).to.equal('Reauthentication already in progress.');
16-
});
11+
it('returns an error', async function () {
12+
const error = await provider.reauth(context).then(
13+
() => null,
14+
error => error
15+
);
16+
expect(error).to.exist;
17+
expect(error).to.be.instanceOf(MongoRuntimeError);
18+
expect(error?.message).to.equal('Reauthentication already in progress.');
1719
});
1820
});
1921
});

0 commit comments

Comments
 (0)