mongodb 4.6.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/admin.js +5 -5
- package/lib/admin.js.map +1 -1
- package/lib/bulk/common.js +4 -4
- package/lib/bulk/common.js.map +1 -1
- package/lib/change_stream.js +37 -28
- package/lib/change_stream.js.map +1 -1
- package/lib/cmap/auth/scram.js +12 -1
- package/lib/cmap/auth/scram.js.map +1 -1
- package/lib/cmap/connection.js +9 -1
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +70 -57
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/connection_pool_events.js.map +1 -1
- package/lib/cmap/message_stream.js +39 -6
- package/lib/cmap/message_stream.js.map +1 -1
- package/lib/cmap/wire_protocol/compression.js +18 -2
- package/lib/cmap/wire_protocol/compression.js.map +1 -1
- package/lib/cmap/wire_protocol/constants.js +2 -2
- package/lib/cmap/wire_protocol/shared.js +3 -0
- package/lib/cmap/wire_protocol/shared.js.map +1 -1
- package/lib/collection.js +30 -30
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +10 -0
- package/lib/connection_string.js.map +1 -1
- package/lib/cursor/abstract_cursor.js +16 -11
- package/lib/cursor/abstract_cursor.js.map +1 -1
- package/lib/cursor/aggregation_cursor.js +5 -5
- package/lib/cursor/aggregation_cursor.js.map +1 -1
- package/lib/cursor/find_cursor.js +6 -6
- package/lib/cursor/find_cursor.js.map +1 -1
- package/lib/db.js +14 -14
- package/lib/db.js.map +1 -1
- package/lib/deps.js +6 -1
- package/lib/deps.js.map +1 -1
- package/lib/encrypter.js +9 -2
- package/lib/encrypter.js.map +1 -1
- package/lib/mongo_client.js +11 -0
- package/lib/mongo_client.js.map +1 -1
- package/lib/operations/connect.js +1 -0
- package/lib/operations/connect.js.map +1 -1
- package/lib/operations/create_collection.js +8 -3
- package/lib/operations/create_collection.js.map +1 -1
- package/lib/operations/drop.js +1 -20
- package/lib/operations/drop.js.map +1 -1
- package/lib/operations/estimated_document_count.js +1 -20
- package/lib/operations/estimated_document_count.js.map +1 -1
- package/lib/operations/execute_operation.js +15 -9
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/indexes.js +2 -2
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/list_collections.js +2 -2
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/sdam/monitor.js +10 -3
- package/lib/sdam/monitor.js.map +1 -1
- package/lib/sdam/srv_polling.js +2 -1
- package/lib/sdam/srv_polling.js.map +1 -1
- package/lib/sdam/topology.js +3 -2
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sessions.js +29 -17
- package/lib/sessions.js.map +1 -1
- package/lib/utils.js +3 -2
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +229 -37
- package/package.json +10 -9
- package/src/admin.ts +9 -5
- package/src/bulk/common.ts +4 -4
- package/src/change_stream.ts +250 -47
- package/src/cmap/auth/scram.ts +11 -1
- package/src/cmap/connection.ts +11 -0
- package/src/cmap/connection_pool.ts +90 -74
- package/src/cmap/connection_pool_events.ts +1 -1
- package/src/cmap/message_stream.ts +41 -7
- package/src/cmap/wire_protocol/compression.ts +27 -3
- package/src/cmap/wire_protocol/constants.ts +2 -2
- package/src/cmap/wire_protocol/shared.ts +5 -1
- package/src/collection.ts +38 -31
- package/src/connection_string.ts +10 -0
- package/src/cursor/abstract_cursor.ts +16 -13
- package/src/cursor/aggregation_cursor.ts +6 -6
- package/src/cursor/find_cursor.ts +7 -7
- package/src/db.ts +18 -14
- package/src/deps.ts +41 -12
- package/src/encrypter.ts +8 -2
- package/src/index.ts +9 -0
- package/src/mongo_client.ts +18 -1
- package/src/operations/connect.ts +1 -0
- package/src/operations/create_collection.ts +13 -3
- package/src/operations/drop.ts +1 -23
- package/src/operations/estimated_document_count.ts +2 -29
- package/src/operations/execute_operation.ts +25 -26
- package/src/operations/indexes.ts +3 -9
- package/src/operations/list_collections.ts +3 -3
- package/src/sdam/monitor.ts +10 -0
- package/src/sdam/srv_polling.ts +1 -0
- package/src/sdam/topology.ts +6 -2
- package/src/sessions.ts +31 -20
- package/src/transactions.ts +1 -1
- package/src/utils.ts +2 -1
package/src/deps.ts
CHANGED
|
@@ -44,6 +44,30 @@ export interface KerberosClient {
|
|
|
44
44
|
unwrap: (challenge: string, callback?: Callback<string>) => Promise<string> | void;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
type ZStandardLib = {
|
|
48
|
+
/**
|
|
49
|
+
* Compress using zstd.
|
|
50
|
+
* @param buf - Buffer to be compressed.
|
|
51
|
+
*/
|
|
52
|
+
compress(buf: Buffer, level?: number): Promise<Buffer>;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Decompress using zstd.
|
|
56
|
+
*/
|
|
57
|
+
decompress(buf: Buffer): Promise<Buffer>;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export let ZStandard: ZStandardLib | { kModuleError: MongoMissingDependencyError } =
|
|
61
|
+
makeErrorModule(
|
|
62
|
+
new MongoMissingDependencyError(
|
|
63
|
+
'Optional module `@mongodb-js/zstd` not found. Please install it to enable zstd compression'
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
ZStandard = require('@mongodb-js/zstd');
|
|
69
|
+
} catch {} // eslint-disable-line
|
|
70
|
+
|
|
47
71
|
type SnappyLib = {
|
|
48
72
|
[PKG_VERSION]: { major: number; minor: number; patch: number };
|
|
49
73
|
|
|
@@ -300,7 +324,7 @@ export interface AutoEncryptionOptions {
|
|
|
300
324
|
/** Command line arguments to use when auto-spawning a mongocryptd */
|
|
301
325
|
mongocryptdSpawnArgs?: string[];
|
|
302
326
|
/**
|
|
303
|
-
* Full path to a
|
|
327
|
+
* Full path to a MongoDB Crypt shared library to be used (instead of mongocryptd).
|
|
304
328
|
*
|
|
305
329
|
* This needs to be the path to the file itself, not a directory.
|
|
306
330
|
* It can be an absolute or relative path. If the path is relative and
|
|
@@ -308,32 +332,36 @@ export interface AutoEncryptionOptions {
|
|
|
308
332
|
* containing the mongodb-client-encryption native addon file. Otherwise,
|
|
309
333
|
* the path will be interpreted relative to the current working directory.
|
|
310
334
|
*
|
|
311
|
-
* Currently, loading different
|
|
335
|
+
* Currently, loading different MongoDB Crypt shared library files from different
|
|
312
336
|
* MongoClients in the same process is not supported.
|
|
313
337
|
*
|
|
314
|
-
* If this option is provided and no
|
|
338
|
+
* If this option is provided and no MongoDB Crypt shared library could be loaded
|
|
315
339
|
* from the specified location, creating the MongoClient will fail.
|
|
316
340
|
*
|
|
317
|
-
* If this option is not provided and `
|
|
341
|
+
* If this option is not provided and `cryptSharedLibRequired` is not specified,
|
|
318
342
|
* the AutoEncrypter will attempt to spawn and/or use mongocryptd according
|
|
319
343
|
* to the mongocryptd-specific `extraOptions` options.
|
|
320
344
|
*
|
|
321
345
|
* Specifying a path prevents mongocryptd from being used as a fallback.
|
|
346
|
+
*
|
|
347
|
+
* @experimental Requires the MongoDB Crypt shared library, available in MongoDB 6.0 or higher.
|
|
322
348
|
*/
|
|
323
|
-
|
|
349
|
+
cryptSharedLibPath?: string;
|
|
324
350
|
/**
|
|
325
|
-
* If specified, never use mongocryptd and instead fail when the
|
|
326
|
-
* could not be loaded.
|
|
351
|
+
* If specified, never use mongocryptd and instead fail when the MongoDB Crypt
|
|
352
|
+
* shared library could not be loaded.
|
|
327
353
|
*
|
|
328
|
-
* This is always true when `
|
|
354
|
+
* This is always true when `cryptSharedLibPath` is specified.
|
|
355
|
+
*
|
|
356
|
+
* @experimental Requires the MongoDB Crypt shared library, available in MongoDB 6.0 or higher.
|
|
329
357
|
*/
|
|
330
|
-
|
|
358
|
+
cryptSharedLibRequired?: boolean;
|
|
331
359
|
/**
|
|
332
|
-
* Search paths for a
|
|
360
|
+
* Search paths for a MongoDB Crypt shared library to be used (instead of mongocryptd)
|
|
333
361
|
* Only for driver testing!
|
|
334
362
|
* @internal
|
|
335
363
|
*/
|
|
336
|
-
|
|
364
|
+
cryptSharedLibSearchPaths?: string[];
|
|
337
365
|
};
|
|
338
366
|
proxyOptions?: ProxyOptions;
|
|
339
367
|
/** The TLS options to use connecting to the KMS provider */
|
|
@@ -354,5 +382,6 @@ export interface AutoEncrypter {
|
|
|
354
382
|
teardown(force: boolean, callback: Callback): void;
|
|
355
383
|
encrypt(ns: string, cmd: Document, options: any, callback: Callback<Document>): void;
|
|
356
384
|
decrypt(cmd: Document, options: any, callback: Callback<Document>): void;
|
|
357
|
-
|
|
385
|
+
/** @experimental */
|
|
386
|
+
readonly cryptSharedLibVersionInfo: { version: bigint; versionStr: string } | null;
|
|
358
387
|
}
|
package/src/encrypter.ts
CHANGED
|
@@ -124,9 +124,15 @@ export class Encrypter {
|
|
|
124
124
|
|
|
125
125
|
static checkForMongoCrypt(): void {
|
|
126
126
|
let mongodbClientEncryption = undefined;
|
|
127
|
+
// Ensure you always wrap an optional require in the try block NODE-3199
|
|
127
128
|
try {
|
|
128
|
-
//
|
|
129
|
-
|
|
129
|
+
// Note (NODE-4254): This is to get around the circular dependency between
|
|
130
|
+
// mongodb-client-encryption and the driver in the test scenarios.
|
|
131
|
+
if (process.env.MONGODB_CLIENT_ENCRYPTION_OVERRIDE) {
|
|
132
|
+
mongodbClientEncryption = require(process.env.MONGODB_CLIENT_ENCRYPTION_OVERRIDE);
|
|
133
|
+
} else {
|
|
134
|
+
mongodbClientEncryption = require('mongodb-client-encryption');
|
|
135
|
+
}
|
|
130
136
|
} catch (err) {
|
|
131
137
|
throw new MongoMissingDependencyError(
|
|
132
138
|
'Auto-encryption requested, but the module is not installed. ' +
|
package/src/index.ts
CHANGED
|
@@ -171,21 +171,30 @@ export type { UnorderedBulkOperation } from './bulk/unordered';
|
|
|
171
171
|
export type {
|
|
172
172
|
ChangeStream,
|
|
173
173
|
ChangeStreamAggregateRawResult,
|
|
174
|
+
ChangeStreamCollModDocument,
|
|
175
|
+
ChangeStreamCreateDocument,
|
|
176
|
+
ChangeStreamCreateIndexDocument,
|
|
174
177
|
ChangeStreamCursor,
|
|
175
178
|
ChangeStreamCursorOptions,
|
|
176
179
|
ChangeStreamDeleteDocument,
|
|
177
180
|
ChangeStreamDocument,
|
|
181
|
+
ChangeStreamDocumentCollectionUUID,
|
|
178
182
|
ChangeStreamDocumentCommon,
|
|
179
183
|
ChangeStreamDocumentKey,
|
|
184
|
+
ChangeStreamDocumentOperationDescription,
|
|
180
185
|
ChangeStreamDropDatabaseDocument,
|
|
181
186
|
ChangeStreamDropDocument,
|
|
187
|
+
ChangeStreamDropIndexDocument,
|
|
182
188
|
ChangeStreamEvents,
|
|
183
189
|
ChangeStreamInsertDocument,
|
|
184
190
|
ChangeStreamInvalidateDocument,
|
|
185
191
|
ChangeStreamNameSpace,
|
|
186
192
|
ChangeStreamOptions,
|
|
193
|
+
ChangeStreamRefineCollectionShardKeyDocument,
|
|
187
194
|
ChangeStreamRenameDocument,
|
|
188
195
|
ChangeStreamReplaceDocument,
|
|
196
|
+
ChangeStreamReshardCollectionDocument,
|
|
197
|
+
ChangeStreamShardCollectionDocument,
|
|
189
198
|
ChangeStreamUpdateDocument,
|
|
190
199
|
OperationTime,
|
|
191
200
|
PipeOptions,
|
package/src/mongo_client.ts
CHANGED
|
@@ -141,6 +141,8 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
|
|
|
141
141
|
maxPoolSize?: number;
|
|
142
142
|
/** The minimum number of connections in the connection pool. */
|
|
143
143
|
minPoolSize?: number;
|
|
144
|
+
/** The maximum number of connections that may be in the process of being established concurrently by the connection pool. */
|
|
145
|
+
maxConnecting?: number;
|
|
144
146
|
/** The maximum number of milliseconds that a connection can remain idle in the pool before being removed and closed. */
|
|
145
147
|
maxIdleTimeMS?: number;
|
|
146
148
|
/** The maximum time in milliseconds that a thread can wait for a connection to become available. */
|
|
@@ -268,11 +270,13 @@ export interface MongoClientPrivate {
|
|
|
268
270
|
sessions: Set<ClientSession>;
|
|
269
271
|
bsonOptions: BSONSerializeOptions;
|
|
270
272
|
namespace: MongoDBNamespace;
|
|
271
|
-
|
|
273
|
+
hasBeenClosed: boolean;
|
|
274
|
+
readonly options: MongoOptions;
|
|
272
275
|
readonly readConcern?: ReadConcern;
|
|
273
276
|
readonly writeConcern?: WriteConcern;
|
|
274
277
|
readonly readPreference: ReadPreference;
|
|
275
278
|
readonly logger: Logger;
|
|
279
|
+
readonly isMongoClient: true;
|
|
276
280
|
}
|
|
277
281
|
|
|
278
282
|
/** @public */
|
|
@@ -351,6 +355,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
|
|
|
351
355
|
sessions: new Set(),
|
|
352
356
|
bsonOptions: resolveBSONOptions(this[kOptions]),
|
|
353
357
|
namespace: ns('admin'),
|
|
358
|
+
hasBeenClosed: false,
|
|
354
359
|
|
|
355
360
|
get options() {
|
|
356
361
|
return client[kOptions];
|
|
@@ -366,6 +371,9 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
|
|
|
366
371
|
},
|
|
367
372
|
get logger() {
|
|
368
373
|
return client[kOptions].logger;
|
|
374
|
+
},
|
|
375
|
+
get isMongoClient(): true {
|
|
376
|
+
return true;
|
|
369
377
|
}
|
|
370
378
|
};
|
|
371
379
|
}
|
|
@@ -446,6 +454,14 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
|
|
|
446
454
|
forceOrCallback?: boolean | Callback<void>,
|
|
447
455
|
callback?: Callback<void>
|
|
448
456
|
): Promise<void> | void {
|
|
457
|
+
// There's no way to set hasBeenClosed back to false
|
|
458
|
+
Object.defineProperty(this.s, 'hasBeenClosed', {
|
|
459
|
+
value: true,
|
|
460
|
+
enumerable: true,
|
|
461
|
+
configurable: false,
|
|
462
|
+
writable: false
|
|
463
|
+
});
|
|
464
|
+
|
|
449
465
|
if (typeof forceOrCallback === 'function') {
|
|
450
466
|
callback = forceOrCallback;
|
|
451
467
|
}
|
|
@@ -638,6 +654,7 @@ export interface MongoOptions
|
|
|
638
654
|
| 'keepAliveInitialDelay'
|
|
639
655
|
| 'localThresholdMS'
|
|
640
656
|
| 'logger'
|
|
657
|
+
| 'maxConnecting'
|
|
641
658
|
| 'maxIdleTimeMS'
|
|
642
659
|
| 'maxPoolSize'
|
|
643
660
|
| 'minPoolSize'
|
|
@@ -62,6 +62,7 @@ function createTopology(
|
|
|
62
62
|
// Events can be emitted before initialization is complete so we have to
|
|
63
63
|
// save the reference to the topology on the client ASAP if the event handlers need to access it
|
|
64
64
|
mongoClient.topology = topology;
|
|
65
|
+
topology.client = mongoClient;
|
|
65
66
|
|
|
66
67
|
topology.once(Topology.OPEN, () => mongoClient.emit('open', mongoClient));
|
|
67
68
|
|
|
@@ -91,6 +91,11 @@ export interface CreateCollectionOptions extends CommandOperationOptions {
|
|
|
91
91
|
expireAfterSeconds?: number;
|
|
92
92
|
/** @experimental */
|
|
93
93
|
encryptedFields?: Document;
|
|
94
|
+
/**
|
|
95
|
+
* If set, enables pre-update and post-update document events to be included for any
|
|
96
|
+
* change streams that listen on this collection.
|
|
97
|
+
*/
|
|
98
|
+
changeStreamPreAndPostImages?: { enabled: boolean };
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
/** @internal */
|
|
@@ -122,13 +127,18 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
|
|
|
122
127
|
db.s.client.options.autoEncryption?.encryptedFieldsMap?.[`${db.databaseName}.${name}`];
|
|
123
128
|
|
|
124
129
|
if (encryptedFields) {
|
|
125
|
-
// Create auxilliary collections for
|
|
130
|
+
// Create auxilliary collections for queryable encryption support.
|
|
126
131
|
const escCollection = encryptedFields.escCollection ?? `enxcol_.${name}.esc`;
|
|
127
132
|
const eccCollection = encryptedFields.eccCollection ?? `enxcol_.${name}.ecc`;
|
|
128
133
|
const ecocCollection = encryptedFields.ecocCollection ?? `enxcol_.${name}.ecoc`;
|
|
129
134
|
|
|
130
135
|
for (const collectionName of [escCollection, eccCollection, ecocCollection]) {
|
|
131
|
-
const createOp = new CreateCollectionOperation(db, collectionName
|
|
136
|
+
const createOp = new CreateCollectionOperation(db, collectionName, {
|
|
137
|
+
clusteredIndex: {
|
|
138
|
+
key: { _id: 1 },
|
|
139
|
+
unique: true
|
|
140
|
+
}
|
|
141
|
+
});
|
|
132
142
|
await createOp.executeWithoutEncryptedFieldsCheck(server, session);
|
|
133
143
|
}
|
|
134
144
|
|
|
@@ -140,7 +150,7 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
|
|
|
140
150
|
const coll = await this.executeWithoutEncryptedFieldsCheck(server, session);
|
|
141
151
|
|
|
142
152
|
if (encryptedFields) {
|
|
143
|
-
// Create the required index for
|
|
153
|
+
// Create the required index for queryable encryption support.
|
|
144
154
|
const createIndexOp = new CreateIndexOperation(db, name, { __safeContent__: 1 }, {});
|
|
145
155
|
await new Promise<void>((resolve, reject) => {
|
|
146
156
|
createIndexOp.execute(server, session, err => (err ? reject(err) : resolve()));
|
package/src/operations/drop.ts
CHANGED
|
@@ -51,24 +51,6 @@ export class DropCollectionOperation extends CommandOperation<boolean> {
|
|
|
51
51
|
encryptedFields = listCollectionsResult?.[0]?.options?.encryptedFields;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
let result;
|
|
55
|
-
let errorForMainOperation;
|
|
56
|
-
try {
|
|
57
|
-
result = await this.executeWithoutEncryptedFieldsCheck(server, session);
|
|
58
|
-
} catch (err) {
|
|
59
|
-
if (
|
|
60
|
-
!encryptedFields ||
|
|
61
|
-
!(err instanceof MongoServerError) ||
|
|
62
|
-
err.code !== MONGODB_ERROR_CODES.NamespaceNotFound
|
|
63
|
-
) {
|
|
64
|
-
throw err;
|
|
65
|
-
}
|
|
66
|
-
// Save a possible NamespaceNotFound error for later
|
|
67
|
-
// in the encryptedFields case, so that the auxilliary
|
|
68
|
-
// collections will still be dropped.
|
|
69
|
-
errorForMainOperation = err;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
54
|
if (encryptedFields) {
|
|
73
55
|
const escCollection = encryptedFields.escCollection || `enxcol_.${name}.esc`;
|
|
74
56
|
const eccCollection = encryptedFields.eccCollection || `enxcol_.${name}.ecc`;
|
|
@@ -88,13 +70,9 @@ export class DropCollectionOperation extends CommandOperation<boolean> {
|
|
|
88
70
|
}
|
|
89
71
|
}
|
|
90
72
|
}
|
|
91
|
-
|
|
92
|
-
if (errorForMainOperation) {
|
|
93
|
-
throw errorForMainOperation;
|
|
94
|
-
}
|
|
95
73
|
}
|
|
96
74
|
|
|
97
|
-
return
|
|
75
|
+
return await this.executeWithoutEncryptedFieldsCheck(server, session);
|
|
98
76
|
})().then(
|
|
99
77
|
result => callback(undefined, result),
|
|
100
78
|
err => callback(err)
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { Document } from '../bson';
|
|
2
2
|
import type { Collection } from '../collection';
|
|
3
|
-
import type { MongoServerError } from '../error';
|
|
4
3
|
import type { Server } from '../sdam/server';
|
|
5
4
|
import type { ClientSession } from '../sessions';
|
|
6
|
-
import { Callback
|
|
5
|
+
import type { Callback } from '../utils';
|
|
7
6
|
import { CommandOperation, CommandOperationOptions } from './command';
|
|
8
7
|
import { Aspect, defineAspects } from './operation';
|
|
9
8
|
|
|
@@ -32,32 +31,6 @@ export class EstimatedDocumentCountOperation extends CommandOperation<number> {
|
|
|
32
31
|
server: Server,
|
|
33
32
|
session: ClientSession | undefined,
|
|
34
33
|
callback: Callback<number>
|
|
35
|
-
): void {
|
|
36
|
-
if (maxWireVersion(server) < 12) {
|
|
37
|
-
return this.executeLegacy(server, session, callback);
|
|
38
|
-
}
|
|
39
|
-
const pipeline = [{ $collStats: { count: {} } }, { $group: { _id: 1, n: { $sum: '$count' } } }];
|
|
40
|
-
|
|
41
|
-
const cmd: Document = { aggregate: this.collectionName, pipeline, cursor: {} };
|
|
42
|
-
|
|
43
|
-
if (typeof this.options.maxTimeMS === 'number') {
|
|
44
|
-
cmd.maxTimeMS = this.options.maxTimeMS;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
super.executeCommand(server, session, cmd, (err, response) => {
|
|
48
|
-
if (err && (err as MongoServerError).code !== 26) {
|
|
49
|
-
callback(err);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
callback(undefined, response?.cursor?.firstBatch[0]?.n || 0);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
executeLegacy(
|
|
58
|
-
server: Server,
|
|
59
|
-
session: ClientSession | undefined,
|
|
60
|
-
callback: Callback<number>
|
|
61
34
|
): void {
|
|
62
35
|
const cmd: Document = { count: this.collectionName };
|
|
63
36
|
|
|
@@ -71,7 +44,7 @@ export class EstimatedDocumentCountOperation extends CommandOperation<number> {
|
|
|
71
44
|
return;
|
|
72
45
|
}
|
|
73
46
|
|
|
74
|
-
callback(undefined, response
|
|
47
|
+
callback(undefined, response?.n || 0);
|
|
75
48
|
});
|
|
76
49
|
}
|
|
77
50
|
}
|
|
@@ -7,11 +7,13 @@ import {
|
|
|
7
7
|
MongoError,
|
|
8
8
|
MongoExpiredSessionError,
|
|
9
9
|
MongoNetworkError,
|
|
10
|
+
MongoNotConnectedError,
|
|
10
11
|
MongoRuntimeError,
|
|
11
12
|
MongoServerError,
|
|
12
13
|
MongoTransactionError,
|
|
13
14
|
MongoUnexpectedServerResponseError
|
|
14
15
|
} from '../error';
|
|
16
|
+
import type { MongoClient } from '../mongo_client';
|
|
15
17
|
import { ReadPreference } from '../read_preference';
|
|
16
18
|
import type { Server } from '../sdam/server';
|
|
17
19
|
import {
|
|
@@ -21,13 +23,7 @@ import {
|
|
|
21
23
|
} from '../sdam/server_selection';
|
|
22
24
|
import type { Topology } from '../sdam/topology';
|
|
23
25
|
import type { ClientSession } from '../sessions';
|
|
24
|
-
import {
|
|
25
|
-
Callback,
|
|
26
|
-
getTopology,
|
|
27
|
-
maybePromise,
|
|
28
|
-
supportsRetryableWrites,
|
|
29
|
-
TopologyProvider
|
|
30
|
-
} from '../utils';
|
|
26
|
+
import { Callback, maybePromise, supportsRetryableWrites } from '../utils';
|
|
31
27
|
import { AbstractOperation, Aspect } from './operation';
|
|
32
28
|
|
|
33
29
|
const MMAPv1_RETRY_WRITES_ERROR_CODE = MONGODB_ERROR_CODES.IllegalOperation;
|
|
@@ -66,45 +62,48 @@ export interface ExecutionResult {
|
|
|
66
62
|
export function executeOperation<
|
|
67
63
|
T extends AbstractOperation<TResult>,
|
|
68
64
|
TResult = ResultTypeFromOperation<T>
|
|
69
|
-
>(
|
|
65
|
+
>(client: MongoClient, operation: T): Promise<TResult>;
|
|
70
66
|
export function executeOperation<
|
|
71
67
|
T extends AbstractOperation<TResult>,
|
|
72
68
|
TResult = ResultTypeFromOperation<T>
|
|
73
|
-
>(
|
|
69
|
+
>(client: MongoClient, operation: T, callback: Callback<TResult>): void;
|
|
74
70
|
export function executeOperation<
|
|
75
71
|
T extends AbstractOperation<TResult>,
|
|
76
72
|
TResult = ResultTypeFromOperation<T>
|
|
77
|
-
>(
|
|
78
|
-
topologyProvider: TopologyProvider,
|
|
79
|
-
operation: T,
|
|
80
|
-
callback?: Callback<TResult>
|
|
81
|
-
): Promise<TResult> | void;
|
|
73
|
+
>(client: MongoClient, operation: T, callback?: Callback<TResult>): Promise<TResult> | void;
|
|
82
74
|
export function executeOperation<
|
|
83
75
|
T extends AbstractOperation<TResult>,
|
|
84
76
|
TResult = ResultTypeFromOperation<T>
|
|
85
|
-
>(
|
|
86
|
-
topologyProvider: TopologyProvider,
|
|
87
|
-
operation: T,
|
|
88
|
-
callback?: Callback<TResult>
|
|
89
|
-
): Promise<TResult> | void {
|
|
77
|
+
>(client: MongoClient, operation: T, callback?: Callback<TResult>): Promise<TResult> | void {
|
|
90
78
|
if (!(operation instanceof AbstractOperation)) {
|
|
91
79
|
// TODO(NODE-3483): Extend MongoRuntimeError
|
|
92
80
|
throw new MongoRuntimeError('This method requires a valid operation instance');
|
|
93
81
|
}
|
|
94
82
|
|
|
95
83
|
return maybePromise(callback, callback => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
84
|
+
const topology = client.topology;
|
|
85
|
+
|
|
86
|
+
if (topology == null) {
|
|
87
|
+
if (client.s.hasBeenClosed) {
|
|
88
|
+
return callback(
|
|
89
|
+
new MongoNotConnectedError('Client must be connected before running operations')
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
client.s.options[Symbol.for('@@mdb.skipPingOnConnect')] = true;
|
|
93
|
+
return client.connect(error => {
|
|
94
|
+
delete client.s.options[Symbol.for('@@mdb.skipPingOnConnect')];
|
|
95
|
+
if (error) {
|
|
96
|
+
return callback(error);
|
|
97
|
+
}
|
|
98
|
+
return executeOperation<T, TResult>(client, operation, callback);
|
|
99
|
+
});
|
|
102
100
|
}
|
|
101
|
+
|
|
103
102
|
if (topology.shouldCheckForSessionSupport()) {
|
|
104
103
|
return topology.selectServer(ReadPreference.primaryPreferred, {}, err => {
|
|
105
104
|
if (err) return callback(err);
|
|
106
105
|
|
|
107
|
-
executeOperation<T, TResult>(
|
|
106
|
+
executeOperation<T, TResult>(client, operation, callback);
|
|
108
107
|
});
|
|
109
108
|
}
|
|
110
109
|
|
|
@@ -7,13 +7,7 @@ import type { OneOrMore } from '../mongo_types';
|
|
|
7
7
|
import { ReadPreference } from '../read_preference';
|
|
8
8
|
import type { Server } from '../sdam/server';
|
|
9
9
|
import type { ClientSession } from '../sessions';
|
|
10
|
-
import {
|
|
11
|
-
Callback,
|
|
12
|
-
getTopology,
|
|
13
|
-
maxWireVersion,
|
|
14
|
-
MongoDBNamespace,
|
|
15
|
-
parseIndexOptions
|
|
16
|
-
} from '../utils';
|
|
10
|
+
import { Callback, maxWireVersion, MongoDBNamespace, parseIndexOptions } from '../utils';
|
|
17
11
|
import {
|
|
18
12
|
CollationOptions,
|
|
19
13
|
CommandOperation,
|
|
@@ -424,7 +418,7 @@ export class ListIndexesCursor extends AbstractCursor {
|
|
|
424
418
|
options?: ListIndexesOptions;
|
|
425
419
|
|
|
426
420
|
constructor(collection: Collection, options?: ListIndexesOptions) {
|
|
427
|
-
super(
|
|
421
|
+
super(collection.s.db.s.client, collection.s.namespace, options);
|
|
428
422
|
this.parent = collection;
|
|
429
423
|
this.options = options;
|
|
430
424
|
}
|
|
@@ -444,7 +438,7 @@ export class ListIndexesCursor extends AbstractCursor {
|
|
|
444
438
|
session
|
|
445
439
|
});
|
|
446
440
|
|
|
447
|
-
executeOperation(this.parent, operation, (err, response) => {
|
|
441
|
+
executeOperation(this.parent.s.db.s.client, operation, (err, response) => {
|
|
448
442
|
if (err || response == null) return callback(err);
|
|
449
443
|
|
|
450
444
|
// TODO: NODE-2882
|
|
@@ -3,7 +3,7 @@ import { AbstractCursor } from '../cursor/abstract_cursor';
|
|
|
3
3
|
import type { Db } from '../db';
|
|
4
4
|
import type { Server } from '../sdam/server';
|
|
5
5
|
import type { ClientSession } from '../sessions';
|
|
6
|
-
import { Callback,
|
|
6
|
+
import { Callback, maxWireVersion } from '../utils';
|
|
7
7
|
import { CommandOperation, CommandOperationOptions } from './command';
|
|
8
8
|
import { executeOperation, ExecutionResult } from './execute_operation';
|
|
9
9
|
import { Aspect, defineAspects } from './operation';
|
|
@@ -97,7 +97,7 @@ export class ListCollectionsCursor<
|
|
|
97
97
|
options?: ListCollectionsOptions;
|
|
98
98
|
|
|
99
99
|
constructor(db: Db, filter: Document, options?: ListCollectionsOptions) {
|
|
100
|
-
super(
|
|
100
|
+
super(db.s.client, db.s.namespace, options);
|
|
101
101
|
this.parent = db;
|
|
102
102
|
this.filter = filter;
|
|
103
103
|
this.options = options;
|
|
@@ -118,7 +118,7 @@ export class ListCollectionsCursor<
|
|
|
118
118
|
session
|
|
119
119
|
});
|
|
120
120
|
|
|
121
|
-
executeOperation(this.parent, operation, (err, response) => {
|
|
121
|
+
executeOperation(this.parent.s.client, operation, (err, response) => {
|
|
122
122
|
if (err || response == null) return callback(err);
|
|
123
123
|
|
|
124
124
|
// TODO: NODE-2882
|
package/src/sdam/monitor.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { setTimeout } from 'timers';
|
|
2
|
+
|
|
1
3
|
import { Document, Long } from '../bson';
|
|
2
4
|
import { connect } from '../cmap/connect';
|
|
3
5
|
import { Connection, ConnectionOptions } from '../cmap/connection';
|
|
@@ -88,6 +90,10 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
|
|
|
88
90
|
[kMonitorId]?: InterruptibleAsyncInterval;
|
|
89
91
|
[kRTTPinger]?: RTTPinger;
|
|
90
92
|
|
|
93
|
+
get connection(): Connection | undefined {
|
|
94
|
+
return this[kConnection];
|
|
95
|
+
}
|
|
96
|
+
|
|
91
97
|
constructor(server: Server, options: MonitorOptions) {
|
|
92
98
|
super();
|
|
93
99
|
|
|
@@ -310,6 +316,10 @@ function checkServer(monitor: Monitor, callback: Callback<Document | null>) {
|
|
|
310
316
|
}
|
|
311
317
|
|
|
312
318
|
if (conn) {
|
|
319
|
+
// Tell the connection that we are using the streaming protocol so that the
|
|
320
|
+
// connection's message stream will only read the last hello on the buffer.
|
|
321
|
+
conn.isMonitoringConnection = true;
|
|
322
|
+
|
|
313
323
|
if (isInCloseState(monitor)) {
|
|
314
324
|
conn.destroy({ force: true });
|
|
315
325
|
return;
|
package/src/sdam/srv_polling.ts
CHANGED
package/src/sdam/topology.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import Denque = require('denque');
|
|
2
|
+
import { setTimeout } from 'timers';
|
|
3
|
+
|
|
2
4
|
import type { BSONSerializeOptions, Document } from '../bson';
|
|
3
5
|
import { deserialize, serialize } from '../bson';
|
|
4
6
|
import type { MongoCredentials } from '../cmap/auth/mongo_credentials';
|
|
@@ -27,7 +29,7 @@ import {
|
|
|
27
29
|
MongoServerSelectionError,
|
|
28
30
|
MongoTopologyClosedError
|
|
29
31
|
} from '../error';
|
|
30
|
-
import type { MongoOptions, ServerApi } from '../mongo_client';
|
|
32
|
+
import type { MongoClient, MongoOptions, ServerApi } from '../mongo_client';
|
|
31
33
|
import { TypedEventEmitter } from '../mongo_types';
|
|
32
34
|
import { ReadPreference, ReadPreferenceLike } from '../read_preference';
|
|
33
35
|
import {
|
|
@@ -203,6 +205,8 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
203
205
|
/** @internal */
|
|
204
206
|
_type?: string;
|
|
205
207
|
|
|
208
|
+
client!: MongoClient;
|
|
209
|
+
|
|
206
210
|
/** @event */
|
|
207
211
|
static readonly SERVER_OPENING = SERVER_OPENING;
|
|
208
212
|
/** @event */
|
|
@@ -626,7 +630,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
626
630
|
|
|
627
631
|
/** Start a logical session */
|
|
628
632
|
startSession(options: ClientSessionOptions, clientOptions?: MongoOptions): ClientSession {
|
|
629
|
-
const session = new ClientSession(this, this.s.sessionPool, options, clientOptions);
|
|
633
|
+
const session = new ClientSession(this.client, this.s.sessionPool, options, clientOptions);
|
|
630
634
|
session.once('ended', () => {
|
|
631
635
|
this.s.sessions.delete(session);
|
|
632
636
|
});
|