mongodb-data-service 22.23.2 → 22.23.5
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/connect-mongo-client.js +42 -4
- package/lib/connect-mongo-client.js.map +1 -1
- package/lib/connection-attempt.js +2 -0
- package/lib/connection-attempt.js.map +1 -1
- package/lib/connection-options.d.ts +45 -0
- package/lib/connection-options.d.ts.map +1 -1
- package/lib/csfle-collection-tracker.d.ts +41 -0
- package/lib/csfle-collection-tracker.d.ts.map +1 -1
- package/lib/csfle-collection-tracker.js +43 -0
- package/lib/csfle-collection-tracker.js.map +1 -1
- package/lib/data-service.d.ts +386 -0
- package/lib/data-service.d.ts.map +1 -1
- package/lib/data-service.js +161 -14
- package/lib/data-service.js.map +1 -1
- package/lib/index-detail-helper.d.ts +1 -1
- package/lib/index-detail-helper.d.ts.map +1 -1
- package/lib/index-detail-helper.js +1 -0
- package/lib/index-detail-helper.js.map +1 -1
- package/lib/instance-detail-helper.js +19 -0
- package/lib/instance-detail-helper.js.map +1 -1
- package/lib/run-command.d.ts +25 -0
- package/lib/run-command.d.ts.map +1 -1
- package/lib/run-command.js +23 -1
- package/lib/run-command.js.map +1 -1
- package/package.json +13 -13
package/lib/data-service.js
CHANGED
|
@@ -68,6 +68,11 @@ const maybePickNs = ([ns]) => {
|
|
|
68
68
|
const isPromiseLike = (val) => {
|
|
69
69
|
return 'then' in val && typeof val.then === 'function';
|
|
70
70
|
};
|
|
71
|
+
/**
|
|
72
|
+
* Translates the error message to something human readable.
|
|
73
|
+
* @param error - The error.
|
|
74
|
+
* @returns The error with message translated.
|
|
75
|
+
*/
|
|
71
76
|
const translateErrorMessage = (error) => {
|
|
72
77
|
if (typeof error === 'string') {
|
|
73
78
|
error = { message: error };
|
|
@@ -77,6 +82,13 @@ const translateErrorMessage = (error) => {
|
|
|
77
82
|
}
|
|
78
83
|
return error;
|
|
79
84
|
};
|
|
85
|
+
/**
|
|
86
|
+
* Decorator to do standard op handling that is applied to every public method
|
|
87
|
+
* of the data service
|
|
88
|
+
*
|
|
89
|
+
* - transform error message before throwing
|
|
90
|
+
* - log method success / failure
|
|
91
|
+
*/
|
|
80
92
|
function op(logId, pickLogAttrs = maybePickNs) {
|
|
81
93
|
return function (target, context) {
|
|
82
94
|
const opName = String(context.name);
|
|
@@ -166,6 +178,10 @@ let DataServiceImpl = (() => {
|
|
|
166
178
|
this._isConnecting = false;
|
|
167
179
|
this._useCRUDClient = true;
|
|
168
180
|
this._reauthenticationHandlers = new Set();
|
|
181
|
+
/**
|
|
182
|
+
* Stores the most recent topology description from the server's SDAM events:
|
|
183
|
+
* https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring-monitoring.rst#events
|
|
184
|
+
*/
|
|
169
185
|
this._lastSeenTopology = null;
|
|
170
186
|
this._isWritable = false;
|
|
171
187
|
this._emitter = new events_1.EventEmitter();
|
|
@@ -215,6 +231,9 @@ let DataServiceImpl = (() => {
|
|
|
215
231
|
return this;
|
|
216
232
|
}
|
|
217
233
|
getMongoClientConnectionOptions() {
|
|
234
|
+
// `notifyDeviceFlow` is a function which cannot be serialized for inclusion
|
|
235
|
+
// in the shell, `signal` is an abortSignal, and `allowedFlows` is turned
|
|
236
|
+
// into a function by the connection code.
|
|
218
237
|
return (0, lodash_1.omit)(this._mongoClientConnectionOptions, 'options.oidc.notifyDeviceFlow', 'options.oidc.signal', 'options.oidc.allowedFlows', 'options.oidc.customHttpOptions.agent');
|
|
219
238
|
}
|
|
220
239
|
getConnectionOptions() {
|
|
@@ -277,6 +296,7 @@ let DataServiceImpl = (() => {
|
|
|
277
296
|
},
|
|
278
297
|
{
|
|
279
298
|
$addFields: {
|
|
299
|
+
// `avgObjSize` is the average of per-shard `avgObjSize` weighted by `count`
|
|
280
300
|
avgObjSize: {
|
|
281
301
|
$cond: {
|
|
282
302
|
if: { $ne: ['$count', 0] },
|
|
@@ -298,6 +318,8 @@ let DataServiceImpl = (() => {
|
|
|
298
318
|
}
|
|
299
319
|
catch (error) {
|
|
300
320
|
const message = error.message;
|
|
321
|
+
// We ignore errors for fetching collStats when requesting on an
|
|
322
|
+
// unsupported collection type: either a view or a ADF
|
|
301
323
|
if (message.includes('not valid for Data Lake') ||
|
|
302
324
|
message.includes('is a view, not a collection')) {
|
|
303
325
|
return this._buildCollectionStats(databaseName, collectionName, {});
|
|
@@ -346,6 +368,8 @@ let DataServiceImpl = (() => {
|
|
|
346
368
|
async _listCollections(databaseName, filter = {}, { nameOnly } = {}) {
|
|
347
369
|
try {
|
|
348
370
|
const cursor = this._database(databaseName, 'CRUD').listCollections(filter, { nameOnly });
|
|
371
|
+
// Iterate instead of using .toArray() so we can emit
|
|
372
|
+
// collection info update events as they come in.
|
|
349
373
|
const results = [];
|
|
350
374
|
for await (const result of cursor) {
|
|
351
375
|
if (!nameOnly) {
|
|
@@ -356,6 +380,15 @@ let DataServiceImpl = (() => {
|
|
|
356
380
|
return results;
|
|
357
381
|
}
|
|
358
382
|
catch (err) {
|
|
383
|
+
// Currently Compass should not fail if listCollections failed for
|
|
384
|
+
// any possible reason to preserve current behavior. We probably
|
|
385
|
+
// want this to check at least that what we got back is a server
|
|
386
|
+
// error and not a weird runtime issue on our side that can be
|
|
387
|
+
// swallowed in this case, ideally we know exactly what server
|
|
388
|
+
// errors we want to handle here and only avoid throwing in these
|
|
389
|
+
// cases
|
|
390
|
+
//
|
|
391
|
+
// TODO: https://jira.mongodb.org/browse/COMPASS-5275
|
|
359
392
|
this._logger.warn((0, logger_1.mongoLogId)(1001000099), 'Failed to run listCollections', { message: err.message });
|
|
360
393
|
return [];
|
|
361
394
|
}
|
|
@@ -363,15 +396,29 @@ let DataServiceImpl = (() => {
|
|
|
363
396
|
async listCollections(databaseName, filter = {}, { nameOnly, privileges = null, } = {}) {
|
|
364
397
|
const getCollectionsFromPrivileges = async () => {
|
|
365
398
|
const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
|
|
366
|
-
return Object.keys(
|
|
367
|
-
|
|
399
|
+
return Object.keys(
|
|
400
|
+
// Privileges might not have a database we are looking for
|
|
401
|
+
databases[databaseName] || {})
|
|
402
|
+
.filter(
|
|
403
|
+
// Privileges can have collection name '' that indicates
|
|
404
|
+
// privileges on all collections in the database, we don't want
|
|
405
|
+
// those registered as "real" collection names
|
|
406
|
+
Boolean)
|
|
368
407
|
.map((name) => ({ name }));
|
|
369
408
|
};
|
|
370
409
|
const [listedCollections, collectionsFromPrivileges] = await Promise.all([
|
|
371
410
|
this._listCollections(databaseName, filter, { nameOnly }),
|
|
411
|
+
// If the filter is not empty, we can't meaningfully derive collections
|
|
412
|
+
// from privileges and filter them as the criteria might include any key
|
|
413
|
+
// from the listCollections result object and there is no such info in
|
|
414
|
+
// privileges. Because of that we are ignoring privileges completely if
|
|
415
|
+
// listCollections was called with a filter.
|
|
372
416
|
isEmptyObject(filter) ? getCollectionsFromPrivileges() : [],
|
|
373
417
|
]);
|
|
374
|
-
const collections = uniqueBy(
|
|
418
|
+
const collections = uniqueBy(
|
|
419
|
+
// NB: Order is important, we want listed collections to take precedence
|
|
420
|
+
// if they were fetched successfully
|
|
421
|
+
[...collectionsFromPrivileges, ...listedCollections], 'name').map((coll) => (0, instance_detail_helper_2.adaptCollectionInfo)({ db: databaseName, ...coll }));
|
|
375
422
|
return collections;
|
|
376
423
|
}
|
|
377
424
|
async listDatabases({ nameOnly, privileges = null, roles = null, } = {}) {
|
|
@@ -385,6 +432,14 @@ let DataServiceImpl = (() => {
|
|
|
385
432
|
return databases;
|
|
386
433
|
}
|
|
387
434
|
catch (err) {
|
|
435
|
+
// Currently Compass should not fail if listDatabase failed for any
|
|
436
|
+
// possible reason to preserve current behavior. We probably want this
|
|
437
|
+
// to check at least that what we got back is a server error and not a
|
|
438
|
+
// weird runtime issue on our side that can be swallowed in this case,
|
|
439
|
+
// ideally we know exactly what server errors we want to handle here
|
|
440
|
+
// and only avoid throwing in these cases
|
|
441
|
+
//
|
|
442
|
+
// TODO: https://jira.mongodb.org/browse/COMPASS-5275
|
|
388
443
|
this._logger.warn((0, logger_1.mongoLogId)(1001000098), 'Failed to run listDatabases', { message: err.message });
|
|
389
444
|
return [];
|
|
390
445
|
}
|
|
@@ -392,11 +447,24 @@ let DataServiceImpl = (() => {
|
|
|
392
447
|
const getDatabasesFromPrivileges = async () => {
|
|
393
448
|
const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
|
|
394
449
|
return Object.keys(databases)
|
|
395
|
-
.filter(
|
|
450
|
+
.filter(
|
|
451
|
+
// For the roles created in admin database, the database name
|
|
452
|
+
// can be '' meaning that it applies to all databases. We can't
|
|
453
|
+
// meaningfully handle this in the UI so we are filtering these
|
|
454
|
+
// out
|
|
455
|
+
Boolean)
|
|
396
456
|
.map((name) => ({ name }));
|
|
397
457
|
};
|
|
398
458
|
const getDatabasesFromRoles = async () => {
|
|
399
|
-
const databases = (0, instance_detail_helper_2.getDatabasesByRoles)(await this._getRolesOrFallback(roles),
|
|
459
|
+
const databases = (0, instance_detail_helper_2.getDatabasesByRoles)(await this._getRolesOrFallback(roles),
|
|
460
|
+
// https://jira.mongodb.org/browse/HELP-32199
|
|
461
|
+
// Atlas shared tier MongoDB server version v5+ does not return
|
|
462
|
+
// `authenticatedUserPrivileges` as part of the `connectionStatus`.
|
|
463
|
+
// As a workaround we show the databases the user has
|
|
464
|
+
// certain general built-in roles for.
|
|
465
|
+
// This does not cover custom user roles which can
|
|
466
|
+
// have custom privileges that we can't currently fetch.
|
|
467
|
+
['read', 'readWrite', 'dbAdmin', 'dbOwner']);
|
|
400
468
|
return databases.map((name) => ({ name }));
|
|
401
469
|
};
|
|
402
470
|
const [listedDatabases, databasesFromPrivileges, databasesFromRoles] = await Promise.all([
|
|
@@ -404,7 +472,10 @@ let DataServiceImpl = (() => {
|
|
|
404
472
|
getDatabasesFromPrivileges(),
|
|
405
473
|
getDatabasesFromRoles(),
|
|
406
474
|
]);
|
|
407
|
-
const databases = uniqueBy(
|
|
475
|
+
const databases = uniqueBy(
|
|
476
|
+
// NB: Order is important, we want listed collections to take precedence
|
|
477
|
+
// if they were fetched successfully
|
|
478
|
+
[...databasesFromRoles, ...databasesFromPrivileges, ...listedDatabases], 'name').map((db) => {
|
|
408
479
|
return { _id: db.name, name: db.name, ...(0, instance_detail_helper_2.adaptDatabaseInfo)(db) };
|
|
409
480
|
});
|
|
410
481
|
return databases;
|
|
@@ -549,6 +620,7 @@ let DataServiceImpl = (() => {
|
|
|
549
620
|
.toArray();
|
|
550
621
|
}
|
|
551
622
|
catch {
|
|
623
|
+
// ignore
|
|
552
624
|
}
|
|
553
625
|
const options = {};
|
|
554
626
|
const encryptedFieldsInfo = result?.options?.encryptedFields;
|
|
@@ -600,6 +672,8 @@ let DataServiceImpl = (() => {
|
|
|
600
672
|
aggregateCursor(ns, pipeline, options = {}) {
|
|
601
673
|
return this._collection(ns, 'CRUD').aggregate(pipeline, options);
|
|
602
674
|
}
|
|
675
|
+
// @ts-expect-error generic in the method trips up TS here resulting in
|
|
676
|
+
// Promise<unknown> is not assignable to Promise<Document[]>
|
|
603
677
|
aggregate(ns, pipeline, options = {}, executionOptions) {
|
|
604
678
|
let cursor;
|
|
605
679
|
return this._cancellableOperation(async (session) => {
|
|
@@ -644,7 +718,7 @@ let DataServiceImpl = (() => {
|
|
|
644
718
|
return await coll.replaceOne(filter, replacement, options);
|
|
645
719
|
}
|
|
646
720
|
explainFind(ns, filter, options = {}, executionOptions) {
|
|
647
|
-
const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.
|
|
721
|
+
const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats;
|
|
648
722
|
let cursor;
|
|
649
723
|
return this._cancellableOperation(async (session) => {
|
|
650
724
|
cursor = this._collection(ns, 'CRUD').find(filter, {
|
|
@@ -657,7 +731,7 @@ let DataServiceImpl = (() => {
|
|
|
657
731
|
}, () => cursor?.close(), executionOptions?.abortSignal);
|
|
658
732
|
}
|
|
659
733
|
explainAggregate(ns, pipeline, options, executionOptions) {
|
|
660
|
-
const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.
|
|
734
|
+
const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats;
|
|
661
735
|
let cursor;
|
|
662
736
|
return this._cancellableOperation(async (session) => {
|
|
663
737
|
cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
|
|
@@ -737,6 +811,7 @@ let DataServiceImpl = (() => {
|
|
|
737
811
|
async instance() {
|
|
738
812
|
return {
|
|
739
813
|
...(await (0, instance_detail_helper_2.getInstance)(this._initializedClient('META'), this._connectionOptions.connectionString)),
|
|
814
|
+
// Need to get the CSFLE flag from the CRUD client, not the META one
|
|
740
815
|
csfleMode: this.getCSFLEMode(),
|
|
741
816
|
};
|
|
742
817
|
}
|
|
@@ -748,13 +823,21 @@ let DataServiceImpl = (() => {
|
|
|
748
823
|
const coll = this._collection(ns, 'CRUD');
|
|
749
824
|
return await coll.insertMany(docs, options);
|
|
750
825
|
}
|
|
751
|
-
async updateCollection(ns,
|
|
826
|
+
async updateCollection(ns,
|
|
827
|
+
// Collection name to update that will be passed to the collMod command will
|
|
828
|
+
// be derived from the provided namespace, this is why we are explicitly
|
|
829
|
+
// prohibiting to pass collMod flag here
|
|
830
|
+
flags = {}) {
|
|
752
831
|
const collectionName = this._collectionName(ns);
|
|
753
832
|
const db = this._database(ns, 'CRUD');
|
|
754
833
|
const result = await (0, run_command_1.runCommand)(db, {
|
|
834
|
+
// Order of arguments is important here, collMod is a command name and it
|
|
835
|
+
// should always be the first one in the object
|
|
755
836
|
collMod: collectionName,
|
|
756
837
|
...flags,
|
|
757
838
|
});
|
|
839
|
+
// Reset the CSFLE-enabled client (if any) to clear any collection
|
|
840
|
+
// metadata caches that might still be active.
|
|
758
841
|
await this._resetCRUDClient();
|
|
759
842
|
return result;
|
|
760
843
|
}
|
|
@@ -807,6 +890,7 @@ let DataServiceImpl = (() => {
|
|
|
807
890
|
size: size === 0 ? 0 : size || 1000,
|
|
808
891
|
},
|
|
809
892
|
});
|
|
893
|
+
// add $project stage if projection (fields) was specified
|
|
810
894
|
if (fields && Object.keys(fields).length > 0) {
|
|
811
895
|
pipeline.push({
|
|
812
896
|
$project: fields,
|
|
@@ -836,6 +920,9 @@ let DataServiceImpl = (() => {
|
|
|
836
920
|
});
|
|
837
921
|
}
|
|
838
922
|
isConnected() {
|
|
923
|
+
// This is better than just returning internal `_isConnecting` as this
|
|
924
|
+
// actually shows when the client is available on the NativeClient instance
|
|
925
|
+
// and connected
|
|
839
926
|
return !!this._metadataClient;
|
|
840
927
|
}
|
|
841
928
|
async _cancellableOperation(start, stop = () => Promise.resolve(), abortSignal) {
|
|
@@ -843,6 +930,7 @@ let DataServiceImpl = (() => {
|
|
|
843
930
|
return await start();
|
|
844
931
|
}
|
|
845
932
|
if (abortSignal.aborted) {
|
|
933
|
+
// AbortSignal.reason is supported from node v17.2.0.
|
|
846
934
|
throw abortSignal.reason ?? (0, compass_utils_1.createCancelError)();
|
|
847
935
|
}
|
|
848
936
|
const session = this._startSession('CRUD');
|
|
@@ -904,10 +992,15 @@ let DataServiceImpl = (() => {
|
|
|
904
992
|
this._lastSeenTopology = evt.newDescription;
|
|
905
993
|
this._emitter.emit('topologyDescriptionChanged', evt);
|
|
906
994
|
});
|
|
995
|
+
// Heartbeat events are fairly noisy. We put some effort into
|
|
996
|
+
// making sure that we only log events that actually contain
|
|
997
|
+
// meaningful information.
|
|
907
998
|
const heartbeatStatusMap = new Map();
|
|
908
999
|
const isSignificantDurationChange = (before, after) => {
|
|
1000
|
+
// Changes in pings below 200ms are not particularly concerning here.
|
|
909
1001
|
before = Math.max(before, 200);
|
|
910
1002
|
after = Math.max(after, 200);
|
|
1003
|
+
// Check if changes is at least 2× (in either direction).
|
|
911
1004
|
return Math.abs(Math.log2(before / after)) >= 1;
|
|
912
1005
|
};
|
|
913
1006
|
client.on('serverHeartbeatSucceeded', (evt) => {
|
|
@@ -1007,6 +1100,8 @@ let DataServiceImpl = (() => {
|
|
|
1007
1100
|
.find(filter, {
|
|
1008
1101
|
session,
|
|
1009
1102
|
maxTimeMS: remainingTimeoutMS(),
|
|
1103
|
+
// by using promoteValues: false we can spot BSON type changes
|
|
1104
|
+
// when diffing. ie. new Double(1) -> new Int32(1)
|
|
1010
1105
|
promoteValues: false,
|
|
1011
1106
|
})
|
|
1012
1107
|
.sort({ _id: 1 })
|
|
@@ -1038,8 +1133,14 @@ let DataServiceImpl = (() => {
|
|
|
1038
1133
|
}
|
|
1039
1134
|
catch (err) {
|
|
1040
1135
|
if (isTransactionAbortError(err)) {
|
|
1136
|
+
// The transaction was aborted while it was still calculating the
|
|
1137
|
+
// preview. Just return something here rather than erroring. No
|
|
1138
|
+
// reason to abort the transaction or end the session again because
|
|
1139
|
+
// we only got here because that already happened.
|
|
1041
1140
|
return { changes: [] };
|
|
1042
1141
|
}
|
|
1142
|
+
// The only way this if statement would be true is if aborting the
|
|
1143
|
+
// transaction and ending the session itself failed above. Unlikely.
|
|
1043
1144
|
if (session.inTransaction()) {
|
|
1044
1145
|
await session.abortTransaction();
|
|
1045
1146
|
await session.endSession();
|
|
@@ -1047,8 +1148,19 @@ let DataServiceImpl = (() => {
|
|
|
1047
1148
|
throw err;
|
|
1048
1149
|
}
|
|
1049
1150
|
}, async () => {
|
|
1151
|
+
// Rely on the session being killed when we cancel the operation. It can
|
|
1152
|
+
// take a few seconds before the driver reacts, but the Promise.race()
|
|
1153
|
+
// against the abort signal should cause the UI to immediately be
|
|
1154
|
+
// notified that the operation was cancelled. We don't abort the
|
|
1155
|
+
// transaction or end the session as well because the code we run inside
|
|
1156
|
+
// session.withTransaction() above would experience race conditions.
|
|
1050
1157
|
}, abortSignal);
|
|
1051
1158
|
}
|
|
1159
|
+
/**
|
|
1160
|
+
* @param databaseName - The name of the database.
|
|
1161
|
+
* @param collectionName - The name of the collection.
|
|
1162
|
+
* @param data - The result of the collStats command.
|
|
1163
|
+
*/
|
|
1052
1164
|
_buildCollectionStats(databaseName, collectionName, data) {
|
|
1053
1165
|
return {
|
|
1054
1166
|
ns: databaseName + '.' + collectionName,
|
|
@@ -1064,20 +1176,47 @@ let DataServiceImpl = (() => {
|
|
|
1064
1176
|
index_size: data.totalIndexSize ?? 0,
|
|
1065
1177
|
};
|
|
1066
1178
|
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Get the collection to operate on.
|
|
1181
|
+
*
|
|
1182
|
+
* @param ns - The namespace.
|
|
1183
|
+
*/
|
|
1067
1184
|
_collection(ns, type) {
|
|
1068
1185
|
return this._initializedClient(type)
|
|
1069
1186
|
.db(this._databaseName(ns))
|
|
1070
1187
|
.collection(this._collectionName(ns));
|
|
1071
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Get the database to operate on.
|
|
1191
|
+
*
|
|
1192
|
+
* @param ns - The namespace.
|
|
1193
|
+
*/
|
|
1072
1194
|
_database(ns, type) {
|
|
1073
1195
|
return this._initializedClient(type).db(this._databaseName(ns));
|
|
1074
1196
|
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Get the collection name from a namespace.
|
|
1199
|
+
*
|
|
1200
|
+
* @param ns - The namespace in database.collection format.
|
|
1201
|
+
*/
|
|
1075
1202
|
_collectionName(ns) {
|
|
1076
1203
|
return (0, mongodb_ns_1.default)(ns).collection;
|
|
1077
1204
|
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Get the database name from a namespace.
|
|
1207
|
+
*
|
|
1208
|
+
* @param ns - The namespace in database.collection format.
|
|
1209
|
+
*/
|
|
1078
1210
|
_databaseName(ns) {
|
|
1079
1211
|
return (0, mongodb_ns_1.default)(ns).database;
|
|
1080
1212
|
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Determine if the hello response indicates a writable server.
|
|
1215
|
+
*
|
|
1216
|
+
* @param evt - The topology description changed event.
|
|
1217
|
+
*
|
|
1218
|
+
* @returns If the server is writable.
|
|
1219
|
+
*/
|
|
1081
1220
|
_checkIsWritable(evt) {
|
|
1082
1221
|
return [...evt.newDescription.servers.values()].some((server) => server.isWritable);
|
|
1083
1222
|
}
|
|
@@ -1095,10 +1234,12 @@ let DataServiceImpl = (() => {
|
|
|
1095
1234
|
}
|
|
1096
1235
|
async _resetCRUDClient() {
|
|
1097
1236
|
if (this.getCSFLEMode() === 'unavailable') {
|
|
1237
|
+
// No separate client in use, don't do anything
|
|
1098
1238
|
return;
|
|
1099
1239
|
}
|
|
1100
1240
|
const crudClient = this._crudClient;
|
|
1101
1241
|
if (!crudClient) {
|
|
1242
|
+
// In disconnected state, don't do anything
|
|
1102
1243
|
return;
|
|
1103
1244
|
}
|
|
1104
1245
|
const newClient = await crudClient[connect_mongo_client_1.createClonedClient]();
|
|
@@ -1107,6 +1248,9 @@ let DataServiceImpl = (() => {
|
|
|
1107
1248
|
await crudClient.close();
|
|
1108
1249
|
}
|
|
1109
1250
|
else {
|
|
1251
|
+
// If _crudClient has changed between start and end of
|
|
1252
|
+
// connection establishment, don't do anything, just
|
|
1253
|
+
// close and discard the new client.
|
|
1110
1254
|
await newClient.close();
|
|
1111
1255
|
}
|
|
1112
1256
|
}
|
|
@@ -1255,15 +1399,13 @@ let DataServiceImpl = (() => {
|
|
|
1255
1399
|
_explainFind_decorators = [op((0, logger_1.mongoLogId)(1001000046), ([ns, , , executionOptions]) => {
|
|
1256
1400
|
return {
|
|
1257
1401
|
ns,
|
|
1258
|
-
verbosity: executionOptions?.explainVerbosity ||
|
|
1259
|
-
mongodb_1.ExplainVerbosity.allPlansExecution,
|
|
1402
|
+
verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
|
|
1260
1403
|
};
|
|
1261
1404
|
})];
|
|
1262
1405
|
_explainAggregate_decorators = [op((0, logger_1.mongoLogId)(1001000177), ([ns, , , executionOptions]) => {
|
|
1263
1406
|
return {
|
|
1264
1407
|
ns,
|
|
1265
|
-
verbosity: executionOptions?.explainVerbosity ||
|
|
1266
|
-
mongodb_1.ExplainVerbosity.allPlansExecution,
|
|
1408
|
+
verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
|
|
1267
1409
|
};
|
|
1268
1410
|
})];
|
|
1269
1411
|
_indexes_decorators = [op((0, logger_1.mongoLogId)(1001000047))];
|
|
@@ -1368,7 +1510,12 @@ let DataServiceImpl = (() => {
|
|
|
1368
1510
|
__esDecorate(_a, null, _dropStreamProcessor_decorators, { kind: "method", name: "dropStreamProcessor", static: false, private: false, access: { has: obj => "dropStreamProcessor" in obj, get: obj => obj.dropStreamProcessor } }, null, _instanceExtraInitializers);
|
|
1369
1511
|
})(),
|
|
1370
1512
|
(() => {
|
|
1371
|
-
const assertNoExtraProps = (
|
|
1513
|
+
const assertNoExtraProps = (
|
|
1514
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1515
|
+
_cls) => {
|
|
1516
|
+
// Checking that we are not exposing anything unexpected on our data service
|
|
1517
|
+
// implementation. This file will not compile if there are more public methods
|
|
1518
|
+
// on the DataServiceImpl than DataService interface allows
|
|
1372
1519
|
};
|
|
1373
1520
|
assertNoExtraProps(_a);
|
|
1374
1521
|
})(),
|