Skip to content

Commit 33fa6b2

Browse files
authored
refactor!: only store topology on MongoClient (#2594)
A topology is now only stored on MongoClient and not on Db or Collection. These classes now store a parent and access the topology through that parent. External topology accessors have been removed, and an internal `getTopology` util has been added. Methods that require a topology can now run into cases where the topology is undefined because the client is closed; an error is thrown in these cases. NODE-2850
1 parent dcb1d20 commit 33fa6b2

16 files changed

+183
-211
lines changed

src/admin.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from './operations/list_databases';
1212
import { executeOperation } from './operations/execute_operation';
1313
import { RunCommandOperation, RunCommandOptions } from './operations/run_command';
14-
import type { Callback } from './utils';
14+
import { Callback, getTopology } from './utils';
1515
import type { Document } from './bson';
1616
import type { CommandOperationOptions } from './operations/command';
1717
import type { Db } from './db';
@@ -83,7 +83,7 @@ export class Admin {
8383
options = Object.assign({ dbName: 'admin' }, options);
8484

8585
return executeOperation(
86-
this.s.db.s.topology,
86+
getTopology(this.s.db),
8787
new RunCommandOperation(this.s.db, command, options),
8888
callback
8989
);
@@ -207,7 +207,7 @@ export class Admin {
207207
options = Object.assign({ dbName: 'admin' }, options);
208208

209209
return executeOperation(
210-
this.s.db.s.topology,
210+
getTopology(this.s.db),
211211
new AddUserOperation(this.s.db, username, password, options),
212212
callback
213213
);
@@ -233,7 +233,7 @@ export class Admin {
233233
options = Object.assign({ dbName: 'admin' }, options);
234234

235235
return executeOperation(
236-
this.s.db.s.topology,
236+
getTopology(this.s.db),
237237
new RemoveUserOperation(this.s.db, username, options),
238238
callback
239239
);
@@ -263,7 +263,7 @@ export class Admin {
263263
options = options || {};
264264

265265
return executeOperation(
266-
this.s.db.s.topology,
266+
getTopology(this.s.db),
267267
new ValidateCollectionOperation(this, collectionName, options),
268268
callback
269269
);
@@ -287,7 +287,7 @@ export class Admin {
287287
options = options || {};
288288

289289
return executeOperation(
290-
this.s.db.s.topology,
290+
getTopology(this.s.db),
291291
new ListDatabasesOperation(this.s.db, options),
292292
callback
293293
);

src/bulk/common.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
hasAtomicOperators,
99
Callback,
1010
MongoDBNamespace,
11-
maxWireVersion
11+
maxWireVersion,
12+
getTopology
1213
} from '../utils';
1314
import { executeOperation } from '../operations/execute_operation';
1415
import { InsertOperation } from '../operations/insert';
@@ -904,7 +905,7 @@ export abstract class BulkOperationBase {
904905
// determine whether bulkOperation is ordered or unordered
905906
this.isOrdered = isOrdered;
906907

907-
const topology = collection.s.topology;
908+
const topology = getTopology(collection);
908909
options = options == null ? {} : options;
909910
// TODO Bring from driver information in isMaster
910911
// Get the namespace for the write operations

src/change_stream.ts

+11-16
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,25 @@ import { EventEmitter } from 'events';
33
import { MongoError, AnyError, isResumableError } from './error';
44
import { Cursor, CursorOptions, CursorStream, CursorStreamOptions } from './cursor/cursor';
55
import { AggregateOperation, AggregateOptions } from './operations/aggregate';
6-
import { loadCollection, loadDb, loadMongoClient } from './dynamic_loaders';
76
import {
87
relayEvents,
98
maxWireVersion,
109
calculateDurationInMs,
1110
now,
1211
maybePromise,
1312
MongoDBNamespace,
14-
Callback
13+
Callback,
14+
getTopology
1515
} from './utils';
1616
import type { ReadPreference } from './read_preference';
1717
import type { Timestamp, Document } from './bson';
1818
import type { Topology } from './sdam/topology';
1919
import type { OperationParent } from './operations/command';
2020
import type { CollationOptions } from './cmap/wire_protocol/write_command';
21+
import { MongoClient } from './mongo_client';
22+
import { Db } from './db';
23+
import { Collection } from './collection';
24+
2125
const kResumeQueue = Symbol('resumeQueue');
2226
const kCursorStream = Symbol('cursorStream');
2327

@@ -172,10 +176,9 @@ export class ChangeStreamStream extends CursorStream {
172176
export class ChangeStream extends EventEmitter {
173177
pipeline: Document[];
174178
options: ChangeStreamOptions;
175-
parent: OperationParent;
179+
parent: MongoClient | Db | Collection;
176180
namespace: MongoDBNamespace;
177181
type: symbol;
178-
topology: Topology;
179182
cursor?: ChangeStreamCursor;
180183
closed: boolean;
181184
streamOptions?: CursorStreamOptions;
@@ -212,31 +215,23 @@ export class ChangeStream extends EventEmitter {
212215
) {
213216
super();
214217

215-
const Collection = loadCollection();
216-
const Db = loadDb();
217-
const MongoClient = loadMongoClient();
218-
219218
this.pipeline = pipeline;
220219
this.options = options;
221220

222-
this.parent = parent;
223-
this.namespace = parent.s.namespace;
224221
if (parent instanceof Collection) {
225222
this.type = CHANGE_DOMAIN_TYPES.COLLECTION;
226-
this.topology = parent.s.db.s.topology;
227223
} else if (parent instanceof Db) {
228224
this.type = CHANGE_DOMAIN_TYPES.DATABASE;
229-
this.topology = parent.s.topology;
230225
} else if (parent instanceof MongoClient) {
231226
this.type = CHANGE_DOMAIN_TYPES.CLUSTER;
232-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
233-
this.topology = parent.topology!;
234227
} else {
235228
throw new TypeError(
236229
'parent provided to ChangeStream constructor is not an instance of Collection, Db, or MongoClient'
237230
);
238231
}
239232

233+
this.parent = parent;
234+
this.namespace = parent.s.namespace;
240235
if (!this.options.readPreference && parent.readPreference) {
241236
this.options.readPreference = parent.readPreference;
242237
}
@@ -483,7 +478,7 @@ function createChangeStreamCursor(
483478
const pipeline = [{ $changeStream: changeStreamStageOptions } as Document].concat(self.pipeline);
484479
const cursorOptions = applyKnownOptions({}, options, CURSOR_OPTIONS);
485480
const changeStreamCursor = new ChangeStreamCursor(
486-
self.topology,
481+
getTopology(self.parent),
487482
new AggregateOperation(self.parent, pipeline, options),
488483
cursorOptions
489484
);
@@ -593,7 +588,7 @@ function processNewChange(
593588
}
594589

595590
function processError(changeStream: ChangeStream, error: AnyError, callback?: Callback) {
596-
const topology = changeStream.topology;
591+
const topology = getTopology(changeStream.parent);
597592
const cursor = changeStream.cursor;
598593

599594
// If the change stream has been closed explicitly, do not process error.

0 commit comments

Comments
 (0)