mongodb-data-service 22.37.2 → 22.38.1
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.map +1 -1
- package/lib/connection-attempt.js +6 -2
- package/lib/connection-attempt.js.map +1 -1
- package/lib/csfle-collection-tracker.js +5 -4
- package/lib/csfle-collection-tracker.js.map +1 -1
- package/lib/data-service.d.ts.map +1 -1
- package/lib/data-service.js +1493 -1475
- package/lib/data-service.js.map +1 -1
- package/package.json +15 -15
package/lib/data-service.js
CHANGED
|
@@ -137,7 +137,6 @@ function op(logId, pickLogAttrs = maybePickNs) {
|
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
let DataServiceImpl = (() => {
|
|
140
|
-
var _a;
|
|
141
140
|
let _classSuper = logger_1.WithLogContext;
|
|
142
141
|
let _instanceExtraInitializers = [];
|
|
143
142
|
let _collectionStats_decorators;
|
|
@@ -188,1589 +187,1608 @@ let DataServiceImpl = (() => {
|
|
|
188
187
|
let _startStreamProcessor_decorators;
|
|
189
188
|
let _stopStreamProcessor_decorators;
|
|
190
189
|
let _dropStreamProcessor_decorators;
|
|
191
|
-
return
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
:
|
|
196
|
-
|
|
197
|
-
|
|
190
|
+
return class DataServiceImpl extends _classSuper {
|
|
191
|
+
static {
|
|
192
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
193
|
+
_collectionStats_decorators = [op((0, logger_1.mongoLogId)(1_001_000_178), ([dbName, collName], result) => {
|
|
194
|
+
return { ns: `${dbName}.${collName}`, ...(result && { result }) };
|
|
195
|
+
})];
|
|
196
|
+
_collectionInfo_decorators = [op((0, logger_1.mongoLogId)(1_001_000_179))];
|
|
197
|
+
_killOp_decorators = [op((0, logger_1.mongoLogId)(1_001_000_031))];
|
|
198
|
+
__connectionStatus_decorators = [op((0, logger_1.mongoLogId)(1_001_000_100))];
|
|
199
|
+
_listCollections_decorators = [op((0, logger_1.mongoLogId)(1_001_000_032), ([databaseName, , options], colls) => {
|
|
200
|
+
return {
|
|
201
|
+
db: databaseName,
|
|
202
|
+
nameOnly: options?.nameOnly ?? false,
|
|
203
|
+
...(colls && { collectionsCount: colls.length }),
|
|
204
|
+
};
|
|
205
|
+
})];
|
|
206
|
+
_listDatabases_decorators = [op((0, logger_1.mongoLogId)(1_001_000_033), ([options], dbs) => {
|
|
207
|
+
return {
|
|
208
|
+
nameOnly: options?.nameOnly ?? false,
|
|
209
|
+
...(dbs && { databasesCount: dbs.length }),
|
|
210
|
+
};
|
|
211
|
+
})];
|
|
212
|
+
_estimatedCount_decorators = [op((0, logger_1.mongoLogId)(1_001_000_034), ([ns, options]) => {
|
|
213
|
+
return { ns, maxTimeMS: options?.maxTimeMS };
|
|
214
|
+
})];
|
|
215
|
+
_count_decorators = [op((0, logger_1.mongoLogId)(1_001_000_035))];
|
|
216
|
+
_createCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_036), ([ns, options], result) => {
|
|
217
|
+
return { ns, options, ...(result && { result }) };
|
|
218
|
+
})];
|
|
219
|
+
_createIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_037), ([ns, spec, options], result) => {
|
|
220
|
+
return { ns, spec, options, ...(result && { result }) };
|
|
221
|
+
})];
|
|
222
|
+
_deleteOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_038), ([ns], result) => {
|
|
223
|
+
return { ns, ...(result && { result }) };
|
|
224
|
+
})];
|
|
225
|
+
_deleteMany_decorators = [op((0, logger_1.mongoLogId)(1_001_000_039), ([ns], result) => {
|
|
226
|
+
return { ns, ...(result && { result }) };
|
|
227
|
+
})];
|
|
228
|
+
_dropCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_059), ([ns], result) => {
|
|
229
|
+
return { ns, ...(result && { result }) };
|
|
230
|
+
})];
|
|
231
|
+
_renameCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_276))];
|
|
232
|
+
_dropDatabase_decorators = [op((0, logger_1.mongoLogId)(1_001_000_040), ([db], result) => {
|
|
233
|
+
return { db, ...(result && { result }) };
|
|
234
|
+
})];
|
|
235
|
+
_dropIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_182), ([ns, name], result) => {
|
|
236
|
+
return { ns, name, ...(result && { result }) };
|
|
237
|
+
})];
|
|
238
|
+
_isListSearchIndexesSupported_decorators = [op((0, logger_1.mongoLogId)(1_001_000_237))];
|
|
239
|
+
_getSearchIndexes_decorators = [op((0, logger_1.mongoLogId)(1_001_000_238))];
|
|
240
|
+
_createSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_239))];
|
|
241
|
+
_updateSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_240))];
|
|
242
|
+
_dropSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_241))];
|
|
243
|
+
_aggregateCursor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_041), ([ns, pipeline, options]) => {
|
|
244
|
+
return {
|
|
245
|
+
ns,
|
|
246
|
+
stages: pipeline.map((stage) => Object.keys(stage)[0]),
|
|
247
|
+
maxTimeMS: options?.maxTimeMS,
|
|
248
|
+
};
|
|
249
|
+
})];
|
|
250
|
+
_aggregate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_181), ([ns, pipeline, options]) => {
|
|
251
|
+
return {
|
|
252
|
+
ns,
|
|
253
|
+
stages: pipeline.map((stage) => Object.keys(stage)[0]),
|
|
254
|
+
maxTimeMS: options?.maxTimeMS,
|
|
255
|
+
};
|
|
256
|
+
})];
|
|
257
|
+
_find_decorators = [op((0, logger_1.mongoLogId)(1_001_000_060), ([ns, , options]) => {
|
|
258
|
+
return { ns, maxTimeMS: options?.maxTimeMS };
|
|
259
|
+
})];
|
|
260
|
+
_findCursor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_043))];
|
|
261
|
+
_findOneAndReplace_decorators = [op((0, logger_1.mongoLogId)(1_001_000_044))];
|
|
262
|
+
_findOneAndUpdate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_045))];
|
|
263
|
+
_updateOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_183))];
|
|
264
|
+
_replaceOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_191))];
|
|
265
|
+
_explainFind_decorators = [op((0, logger_1.mongoLogId)(1_001_000_046), ([ns, , , executionOptions]) => {
|
|
266
|
+
return {
|
|
267
|
+
ns,
|
|
268
|
+
verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
|
|
269
|
+
};
|
|
270
|
+
})];
|
|
271
|
+
_explainAggregate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_177), ([ns, , , executionOptions]) => {
|
|
272
|
+
return {
|
|
273
|
+
ns,
|
|
274
|
+
verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
|
|
275
|
+
};
|
|
276
|
+
})];
|
|
277
|
+
_fetchShardKey_decorators = [op((0, logger_1.mongoLogId)(1_001_000_381))];
|
|
278
|
+
_indexes_decorators = [op((0, logger_1.mongoLogId)(1_001_000_047))];
|
|
279
|
+
_instance_decorators = [op((0, logger_1.mongoLogId)(1_001_000_024), (_, instanceData) => {
|
|
280
|
+
if (instanceData) {
|
|
281
|
+
return {
|
|
282
|
+
serverVersion: instanceData.build.version,
|
|
283
|
+
genuineMongoDB: instanceData.genuineMongoDB,
|
|
284
|
+
dataLake: instanceData.dataLake,
|
|
285
|
+
featureCompatibilityVersion: instanceData.featureCompatibilityVersion,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
})];
|
|
289
|
+
_insertOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_048), ([ns], result) => {
|
|
290
|
+
return { ns, ...(result && { acknowledged: result.acknowledged }) };
|
|
291
|
+
})];
|
|
292
|
+
_insertMany_decorators = [op((0, logger_1.mongoLogId)(1_001_000_049), ([ns], result) => {
|
|
293
|
+
return {
|
|
294
|
+
ns,
|
|
295
|
+
...(result && {
|
|
296
|
+
acknowledged: result.acknowledged,
|
|
297
|
+
insertedCount: result.insertedCount,
|
|
298
|
+
}),
|
|
299
|
+
};
|
|
300
|
+
})];
|
|
301
|
+
_updateCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_050), ([ns], result) => {
|
|
302
|
+
return { ns, ...(result && { result }) };
|
|
303
|
+
})];
|
|
304
|
+
_currentOp_decorators = [op((0, logger_1.mongoLogId)(1_001_000_053))];
|
|
305
|
+
_serverStatus_decorators = [op((0, logger_1.mongoLogId)(1_001_000_061), (_, result) => {
|
|
306
|
+
return result ? { result } : undefined;
|
|
307
|
+
})];
|
|
308
|
+
_top_decorators = [op((0, logger_1.mongoLogId)(1_001_000_062), (_, result) => {
|
|
309
|
+
return result ? { result } : undefined;
|
|
310
|
+
})];
|
|
311
|
+
_createView_decorators = [op((0, logger_1.mongoLogId)(1_001_000_055), ([name, sourceNs, pipeline, options], result) => {
|
|
312
|
+
return {
|
|
313
|
+
name,
|
|
314
|
+
sourceNs,
|
|
315
|
+
stages: pipeline.map((stage) => Object.keys(stage)[0]),
|
|
316
|
+
options,
|
|
317
|
+
...(result && { result }),
|
|
318
|
+
};
|
|
319
|
+
})];
|
|
320
|
+
_databaseStats_decorators = [op((0, logger_1.mongoLogId)(1_001_000_057))];
|
|
321
|
+
_previewUpdate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_266))];
|
|
322
|
+
_createDataKey_decorators = [op((0, logger_1.mongoLogId)(1_001_000_123), ([provider]) => {
|
|
323
|
+
return { provider };
|
|
324
|
+
})];
|
|
325
|
+
_listStreamProcessors_decorators = [op((0, logger_1.mongoLogId)(1_001_000_284))];
|
|
326
|
+
_startStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_285))];
|
|
327
|
+
_stopStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_286))];
|
|
328
|
+
_dropStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_287))];
|
|
329
|
+
__esDecorate(this, null, _collectionStats_decorators, { kind: "method", name: "collectionStats", static: false, private: false, access: { has: obj => "collectionStats" in obj, get: obj => obj.collectionStats }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
330
|
+
__esDecorate(this, null, _collectionInfo_decorators, { kind: "method", name: "collectionInfo", static: false, private: false, access: { has: obj => "collectionInfo" in obj, get: obj => obj.collectionInfo }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
331
|
+
__esDecorate(this, null, _killOp_decorators, { kind: "method", name: "killOp", static: false, private: false, access: { has: obj => "killOp" in obj, get: obj => obj.killOp }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
332
|
+
__esDecorate(this, null, __connectionStatus_decorators, { kind: "method", name: "_connectionStatus", static: false, private: false, access: { has: obj => "_connectionStatus" in obj, get: obj => obj._connectionStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
333
|
+
__esDecorate(this, null, _listCollections_decorators, { kind: "method", name: "listCollections", static: false, private: false, access: { has: obj => "listCollections" in obj, get: obj => obj.listCollections }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
334
|
+
__esDecorate(this, null, _listDatabases_decorators, { kind: "method", name: "listDatabases", static: false, private: false, access: { has: obj => "listDatabases" in obj, get: obj => obj.listDatabases }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
335
|
+
__esDecorate(this, null, _estimatedCount_decorators, { kind: "method", name: "estimatedCount", static: false, private: false, access: { has: obj => "estimatedCount" in obj, get: obj => obj.estimatedCount }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
336
|
+
__esDecorate(this, null, _count_decorators, { kind: "method", name: "count", static: false, private: false, access: { has: obj => "count" in obj, get: obj => obj.count }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
337
|
+
__esDecorate(this, null, _createCollection_decorators, { kind: "method", name: "createCollection", static: false, private: false, access: { has: obj => "createCollection" in obj, get: obj => obj.createCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
338
|
+
__esDecorate(this, null, _createIndex_decorators, { kind: "method", name: "createIndex", static: false, private: false, access: { has: obj => "createIndex" in obj, get: obj => obj.createIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
339
|
+
__esDecorate(this, null, _deleteOne_decorators, { kind: "method", name: "deleteOne", static: false, private: false, access: { has: obj => "deleteOne" in obj, get: obj => obj.deleteOne }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
340
|
+
__esDecorate(this, null, _deleteMany_decorators, { kind: "method", name: "deleteMany", static: false, private: false, access: { has: obj => "deleteMany" in obj, get: obj => obj.deleteMany }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
341
|
+
__esDecorate(this, null, _dropCollection_decorators, { kind: "method", name: "dropCollection", static: false, private: false, access: { has: obj => "dropCollection" in obj, get: obj => obj.dropCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
342
|
+
__esDecorate(this, null, _renameCollection_decorators, { kind: "method", name: "renameCollection", static: false, private: false, access: { has: obj => "renameCollection" in obj, get: obj => obj.renameCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
343
|
+
__esDecorate(this, null, _dropDatabase_decorators, { kind: "method", name: "dropDatabase", static: false, private: false, access: { has: obj => "dropDatabase" in obj, get: obj => obj.dropDatabase }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
344
|
+
__esDecorate(this, null, _dropIndex_decorators, { kind: "method", name: "dropIndex", static: false, private: false, access: { has: obj => "dropIndex" in obj, get: obj => obj.dropIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
345
|
+
__esDecorate(this, null, _isListSearchIndexesSupported_decorators, { kind: "method", name: "isListSearchIndexesSupported", static: false, private: false, access: { has: obj => "isListSearchIndexesSupported" in obj, get: obj => obj.isListSearchIndexesSupported }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
346
|
+
__esDecorate(this, null, _getSearchIndexes_decorators, { kind: "method", name: "getSearchIndexes", static: false, private: false, access: { has: obj => "getSearchIndexes" in obj, get: obj => obj.getSearchIndexes }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
347
|
+
__esDecorate(this, null, _createSearchIndex_decorators, { kind: "method", name: "createSearchIndex", static: false, private: false, access: { has: obj => "createSearchIndex" in obj, get: obj => obj.createSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
348
|
+
__esDecorate(this, null, _updateSearchIndex_decorators, { kind: "method", name: "updateSearchIndex", static: false, private: false, access: { has: obj => "updateSearchIndex" in obj, get: obj => obj.updateSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
349
|
+
__esDecorate(this, null, _dropSearchIndex_decorators, { kind: "method", name: "dropSearchIndex", static: false, private: false, access: { has: obj => "dropSearchIndex" in obj, get: obj => obj.dropSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
350
|
+
__esDecorate(this, null, _aggregateCursor_decorators, { kind: "method", name: "aggregateCursor", static: false, private: false, access: { has: obj => "aggregateCursor" in obj, get: obj => obj.aggregateCursor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
351
|
+
__esDecorate(this, null, _aggregate_decorators, { kind: "method", name: "aggregate", static: false, private: false, access: { has: obj => "aggregate" in obj, get: obj => obj.aggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
352
|
+
__esDecorate(this, null, _find_decorators, { kind: "method", name: "find", static: false, private: false, access: { has: obj => "find" in obj, get: obj => obj.find }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
353
|
+
__esDecorate(this, null, _findCursor_decorators, { kind: "method", name: "findCursor", static: false, private: false, access: { has: obj => "findCursor" in obj, get: obj => obj.findCursor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
354
|
+
__esDecorate(this, null, _findOneAndReplace_decorators, { kind: "method", name: "findOneAndReplace", static: false, private: false, access: { has: obj => "findOneAndReplace" in obj, get: obj => obj.findOneAndReplace }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
355
|
+
__esDecorate(this, null, _findOneAndUpdate_decorators, { kind: "method", name: "findOneAndUpdate", static: false, private: false, access: { has: obj => "findOneAndUpdate" in obj, get: obj => obj.findOneAndUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
356
|
+
__esDecorate(this, null, _updateOne_decorators, { kind: "method", name: "updateOne", static: false, private: false, access: { has: obj => "updateOne" in obj, get: obj => obj.updateOne }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
357
|
+
__esDecorate(this, null, _replaceOne_decorators, { kind: "method", name: "replaceOne", static: false, private: false, access: { has: obj => "replaceOne" in obj, get: obj => obj.replaceOne }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
358
|
+
__esDecorate(this, null, _explainFind_decorators, { kind: "method", name: "explainFind", static: false, private: false, access: { has: obj => "explainFind" in obj, get: obj => obj.explainFind }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
359
|
+
__esDecorate(this, null, _explainAggregate_decorators, { kind: "method", name: "explainAggregate", static: false, private: false, access: { has: obj => "explainAggregate" in obj, get: obj => obj.explainAggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
360
|
+
__esDecorate(this, null, _fetchShardKey_decorators, { kind: "method", name: "fetchShardKey", static: false, private: false, access: { has: obj => "fetchShardKey" in obj, get: obj => obj.fetchShardKey }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
361
|
+
__esDecorate(this, null, _indexes_decorators, { kind: "method", name: "indexes", static: false, private: false, access: { has: obj => "indexes" in obj, get: obj => obj.indexes }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
362
|
+
__esDecorate(this, null, _instance_decorators, { kind: "method", name: "instance", static: false, private: false, access: { has: obj => "instance" in obj, get: obj => obj.instance }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
363
|
+
__esDecorate(this, null, _insertOne_decorators, { kind: "method", name: "insertOne", static: false, private: false, access: { has: obj => "insertOne" in obj, get: obj => obj.insertOne }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
364
|
+
__esDecorate(this, null, _insertMany_decorators, { kind: "method", name: "insertMany", static: false, private: false, access: { has: obj => "insertMany" in obj, get: obj => obj.insertMany }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
365
|
+
__esDecorate(this, null, _updateCollection_decorators, { kind: "method", name: "updateCollection", static: false, private: false, access: { has: obj => "updateCollection" in obj, get: obj => obj.updateCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
366
|
+
__esDecorate(this, null, _currentOp_decorators, { kind: "method", name: "currentOp", static: false, private: false, access: { has: obj => "currentOp" in obj, get: obj => obj.currentOp }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
367
|
+
__esDecorate(this, null, _serverStatus_decorators, { kind: "method", name: "serverStatus", static: false, private: false, access: { has: obj => "serverStatus" in obj, get: obj => obj.serverStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
368
|
+
__esDecorate(this, null, _top_decorators, { kind: "method", name: "top", static: false, private: false, access: { has: obj => "top" in obj, get: obj => obj.top }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
369
|
+
__esDecorate(this, null, _createView_decorators, { kind: "method", name: "createView", static: false, private: false, access: { has: obj => "createView" in obj, get: obj => obj.createView }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
370
|
+
__esDecorate(this, null, _databaseStats_decorators, { kind: "method", name: "databaseStats", static: false, private: false, access: { has: obj => "databaseStats" in obj, get: obj => obj.databaseStats }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
371
|
+
__esDecorate(this, null, _previewUpdate_decorators, { kind: "method", name: "previewUpdate", static: false, private: false, access: { has: obj => "previewUpdate" in obj, get: obj => obj.previewUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
372
|
+
__esDecorate(this, null, _createDataKey_decorators, { kind: "method", name: "createDataKey", static: false, private: false, access: { has: obj => "createDataKey" in obj, get: obj => obj.createDataKey }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
373
|
+
__esDecorate(this, null, _listStreamProcessors_decorators, { kind: "method", name: "listStreamProcessors", static: false, private: false, access: { has: obj => "listStreamProcessors" in obj, get: obj => obj.listStreamProcessors }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
374
|
+
__esDecorate(this, null, _startStreamProcessor_decorators, { kind: "method", name: "startStreamProcessor", static: false, private: false, access: { has: obj => "startStreamProcessor" in obj, get: obj => obj.startStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
375
|
+
__esDecorate(this, null, _stopStreamProcessor_decorators, { kind: "method", name: "stopStreamProcessor", static: false, private: false, access: { has: obj => "stopStreamProcessor" in obj, get: obj => obj.stopStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
376
|
+
__esDecorate(this, null, _dropStreamProcessor_decorators, { kind: "method", name: "dropStreamProcessor", static: false, private: false, access: { has: obj => "dropStreamProcessor" in obj, get: obj => obj.dropStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
377
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
378
|
+
}
|
|
379
|
+
_connectionOptions = __runInitializers(this, _instanceExtraInitializers);
|
|
380
|
+
_proxyOptions;
|
|
381
|
+
_isConnecting = false;
|
|
382
|
+
_mongoClientConnectionOptions;
|
|
383
|
+
// Use two separate clients in the CSFLE case, one with CSFLE
|
|
384
|
+
// enabled, one disabled. _initializedClient() can be used
|
|
385
|
+
// to fetch the right one. _useCRUDClient can be used to control
|
|
386
|
+
// this behavior after connecting, i.e. for disabling and
|
|
387
|
+
// enabling CSFLE on an already-connected DataService instance.
|
|
388
|
+
_metadataClient;
|
|
389
|
+
_crudClient;
|
|
390
|
+
_useCRUDClient = true;
|
|
391
|
+
_csfleCollectionTracker;
|
|
392
|
+
_tunnel;
|
|
393
|
+
_state;
|
|
394
|
+
_reauthenticationHandlers = new Set();
|
|
395
|
+
/**
|
|
396
|
+
* Stores the most recent topology description from the server's SDAM events:
|
|
397
|
+
* https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring-monitoring.rst#events
|
|
398
|
+
*/
|
|
399
|
+
_lastSeenTopology = null;
|
|
400
|
+
_isWritable = false;
|
|
401
|
+
_id;
|
|
402
|
+
_emitter = new events_1.EventEmitter();
|
|
403
|
+
/**
|
|
404
|
+
* Directly used during data-service runtime, auto sets component and context
|
|
405
|
+
* with a connection id
|
|
406
|
+
*/
|
|
407
|
+
_logger;
|
|
408
|
+
/**
|
|
409
|
+
* To be passed to the connect-mongo-client
|
|
410
|
+
*/
|
|
411
|
+
_unboundLogger;
|
|
412
|
+
_getOptionsWithFallbackReadPreference(options, executionOptions) {
|
|
413
|
+
const readPreferencesOverride = isReadPreferenceSet(this._connectionOptions.connectionString)
|
|
414
|
+
? undefined
|
|
415
|
+
: executionOptions?.fallbackReadPreference;
|
|
416
|
+
if (!readPreferencesOverride) {
|
|
417
|
+
return options;
|
|
418
|
+
}
|
|
419
|
+
return {
|
|
420
|
+
...options,
|
|
421
|
+
readPreference: readPreferencesOverride,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
constructor(connectionOptions, logger, proxyOptions) {
|
|
425
|
+
super();
|
|
426
|
+
this._id = id++;
|
|
427
|
+
this._connectionOptions = connectionOptions;
|
|
428
|
+
this._proxyOptions = proxyOptions ?? {};
|
|
429
|
+
const logComponent = 'COMPASS-DATA-SERVICE';
|
|
430
|
+
const logCtx = `Connection ${this._id}`;
|
|
431
|
+
this._logger = {
|
|
432
|
+
debug: (logId, ...args) => {
|
|
433
|
+
return logger?.debug(logComponent, logId, logCtx, ...args);
|
|
434
|
+
},
|
|
435
|
+
info: (logId, ...args) => {
|
|
436
|
+
return logger?.info(logComponent, logId, logCtx, ...args);
|
|
437
|
+
},
|
|
438
|
+
warn: (logId, ...args) => {
|
|
439
|
+
return logger?.warn(logComponent, logId, logCtx, ...args);
|
|
440
|
+
},
|
|
441
|
+
error: (logId, ...args) => {
|
|
442
|
+
return logger?.error(logComponent, logId, logCtx, ...args);
|
|
443
|
+
},
|
|
444
|
+
fatal: (logId, ...args) => {
|
|
445
|
+
return logger?.fatal(logComponent, logId, logCtx, ...args);
|
|
446
|
+
},
|
|
447
|
+
};
|
|
448
|
+
if (logger) {
|
|
449
|
+
this._unboundLogger = Object.assign(logger, { mongoLogId: logger_1.mongoLogId });
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
get id() {
|
|
453
|
+
return this._id;
|
|
454
|
+
}
|
|
455
|
+
on(...args) {
|
|
456
|
+
this._emitter.on(...args);
|
|
457
|
+
return this;
|
|
458
|
+
}
|
|
459
|
+
off(...args) {
|
|
460
|
+
this._emitter.off(...args);
|
|
461
|
+
return this;
|
|
462
|
+
}
|
|
463
|
+
removeListener(...args) {
|
|
464
|
+
this._emitter.off(...args);
|
|
465
|
+
return this;
|
|
466
|
+
}
|
|
467
|
+
once(...args) {
|
|
468
|
+
this._emitter.once(...args);
|
|
469
|
+
return this;
|
|
470
|
+
}
|
|
471
|
+
getMongoClientConnectionOptions() {
|
|
472
|
+
// `notifyDeviceFlow` is a function which cannot be serialized for inclusion
|
|
473
|
+
// in the shell, `signal` is an abortSignal, and `allowedFlows` is turned
|
|
474
|
+
// into a function by the connection code.
|
|
475
|
+
return (0, lodash_1.omit)(this._mongoClientConnectionOptions, 'options.oidc.notifyDeviceFlow', 'options.oidc.signal', 'options.oidc.allowedFlows', 'options.oidc.customFetch', 'options.oidc.customHttpOptions');
|
|
476
|
+
}
|
|
477
|
+
getConnectionOptions() {
|
|
478
|
+
return this._connectionOptions;
|
|
479
|
+
}
|
|
480
|
+
getConnectionString() {
|
|
481
|
+
return new mongodb_connection_string_url_1.default(this._connectionOptions.connectionString);
|
|
482
|
+
}
|
|
483
|
+
setCSFLEEnabled(enabled) {
|
|
484
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_117), 'Setting CSFLE mode', {
|
|
485
|
+
enabled,
|
|
486
|
+
});
|
|
487
|
+
this._useCRUDClient = enabled;
|
|
488
|
+
}
|
|
489
|
+
getCSFLEMode() {
|
|
490
|
+
if (this._crudClient && (0, instance_detail_helper_2.checkIsCSFLEConnection)(this._crudClient)) {
|
|
491
|
+
if (this._useCRUDClient) {
|
|
492
|
+
return 'enabled';
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
return 'disabled';
|
|
198
496
|
}
|
|
199
|
-
return {
|
|
200
|
-
...options,
|
|
201
|
-
readPreference: readPreferencesOverride,
|
|
202
|
-
};
|
|
203
497
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const logComponent = 'COMPASS-DATA-SERVICE';
|
|
221
|
-
const logCtx = `Connection ${this._id}`;
|
|
222
|
-
this._logger = {
|
|
223
|
-
debug: (logId, ...args) => {
|
|
224
|
-
return logger?.debug(logComponent, logId, logCtx, ...args);
|
|
225
|
-
},
|
|
226
|
-
info: (logId, ...args) => {
|
|
227
|
-
return logger?.info(logComponent, logId, logCtx, ...args);
|
|
498
|
+
else {
|
|
499
|
+
return 'unavailable';
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
async collectionStats(databaseName, collectionName, collectionType) {
|
|
503
|
+
const ns = `${databaseName}.${collectionName}`;
|
|
504
|
+
try {
|
|
505
|
+
const coll = this._collection(ns, 'CRUD');
|
|
506
|
+
// Build the aggregation pipeline dynamically based on collection type
|
|
507
|
+
const groupStage = {
|
|
508
|
+
_id: null,
|
|
509
|
+
capped: { $first: '$storageStats.capped' },
|
|
510
|
+
count: { $sum: '$storageStats.count' },
|
|
511
|
+
size: { $sum: { $toDouble: '$storageStats.size' } },
|
|
512
|
+
storageSize: {
|
|
513
|
+
$sum: { $toDouble: '$storageStats.storageSize' },
|
|
228
514
|
},
|
|
229
|
-
|
|
230
|
-
|
|
515
|
+
totalIndexSize: {
|
|
516
|
+
$sum: { $toDouble: '$storageStats.totalIndexSize' },
|
|
231
517
|
},
|
|
232
|
-
|
|
233
|
-
|
|
518
|
+
freeStorageSize: {
|
|
519
|
+
$sum: { $toDouble: '$storageStats.freeStorageSize' },
|
|
234
520
|
},
|
|
235
|
-
|
|
236
|
-
|
|
521
|
+
unscaledCollSize: {
|
|
522
|
+
$sum: {
|
|
523
|
+
$multiply: [
|
|
524
|
+
{ $toDouble: '$storageStats.avgObjSize' },
|
|
525
|
+
{ $toDouble: '$storageStats.count' },
|
|
526
|
+
],
|
|
527
|
+
},
|
|
237
528
|
},
|
|
529
|
+
nindexes: { $max: '$storageStats.nindexes' },
|
|
238
530
|
};
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
get id() {
|
|
244
|
-
return this._id;
|
|
245
|
-
}
|
|
246
|
-
on(...args) {
|
|
247
|
-
this._emitter.on(...args);
|
|
248
|
-
return this;
|
|
249
|
-
}
|
|
250
|
-
off(...args) {
|
|
251
|
-
this._emitter.off(...args);
|
|
252
|
-
return this;
|
|
253
|
-
}
|
|
254
|
-
removeListener(...args) {
|
|
255
|
-
this._emitter.off(...args);
|
|
256
|
-
return this;
|
|
257
|
-
}
|
|
258
|
-
once(...args) {
|
|
259
|
-
this._emitter.once(...args);
|
|
260
|
-
return this;
|
|
261
|
-
}
|
|
262
|
-
getMongoClientConnectionOptions() {
|
|
263
|
-
// `notifyDeviceFlow` is a function which cannot be serialized for inclusion
|
|
264
|
-
// in the shell, `signal` is an abortSignal, and `allowedFlows` is turned
|
|
265
|
-
// into a function by the connection code.
|
|
266
|
-
return (0, lodash_1.omit)(this._mongoClientConnectionOptions, 'options.oidc.notifyDeviceFlow', 'options.oidc.signal', 'options.oidc.allowedFlows', 'options.oidc.customFetch', 'options.oidc.customHttpOptions');
|
|
267
|
-
}
|
|
268
|
-
getConnectionOptions() {
|
|
269
|
-
return this._connectionOptions;
|
|
270
|
-
}
|
|
271
|
-
getConnectionString() {
|
|
272
|
-
return new mongodb_connection_string_url_1.default(this._connectionOptions.connectionString);
|
|
273
|
-
}
|
|
274
|
-
setCSFLEEnabled(enabled) {
|
|
275
|
-
this._logger.info((0, logger_1.mongoLogId)(1_001_000_117), 'Setting CSFLE mode', {
|
|
276
|
-
enabled,
|
|
277
|
-
});
|
|
278
|
-
this._useCRUDClient = enabled;
|
|
279
|
-
}
|
|
280
|
-
getCSFLEMode() {
|
|
281
|
-
if (this._crudClient && (0, instance_detail_helper_2.checkIsCSFLEConnection)(this._crudClient)) {
|
|
282
|
-
if (this._useCRUDClient) {
|
|
283
|
-
return 'enabled';
|
|
284
|
-
}
|
|
285
|
-
else {
|
|
286
|
-
return 'disabled';
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
else {
|
|
290
|
-
return 'unavailable';
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
async collectionStats(databaseName, collectionName, collectionType) {
|
|
294
|
-
const ns = `${databaseName}.${collectionName}`;
|
|
295
|
-
try {
|
|
296
|
-
const coll = this._collection(ns, 'CRUD');
|
|
297
|
-
// Build the aggregation pipeline dynamically based on collection type
|
|
298
|
-
const groupStage = {
|
|
299
|
-
_id: null,
|
|
300
|
-
capped: { $first: '$storageStats.capped' },
|
|
301
|
-
count: { $sum: '$storageStats.count' },
|
|
302
|
-
size: { $sum: { $toDouble: '$storageStats.size' } },
|
|
303
|
-
storageSize: {
|
|
304
|
-
$sum: { $toDouble: '$storageStats.storageSize' },
|
|
305
|
-
},
|
|
306
|
-
totalIndexSize: {
|
|
307
|
-
$sum: { $toDouble: '$storageStats.totalIndexSize' },
|
|
308
|
-
},
|
|
309
|
-
freeStorageSize: {
|
|
310
|
-
$sum: { $toDouble: '$storageStats.freeStorageSize' },
|
|
311
|
-
},
|
|
312
|
-
unscaledCollSize: {
|
|
313
|
-
$sum: {
|
|
314
|
-
$multiply: [
|
|
315
|
-
{ $toDouble: '$storageStats.avgObjSize' },
|
|
316
|
-
{ $toDouble: '$storageStats.count' },
|
|
317
|
-
],
|
|
318
|
-
},
|
|
319
|
-
},
|
|
320
|
-
nindexes: { $max: '$storageStats.nindexes' },
|
|
531
|
+
// Only extract bucket statistics for time series collections
|
|
532
|
+
if (collectionType === 'timeseries') {
|
|
533
|
+
groupStage.timeseriesBucketCount = {
|
|
534
|
+
$first: '$storageStats.timeseries.bucketCount',
|
|
321
535
|
};
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
avgObjSize: {
|
|
335
|
-
$cond: {
|
|
336
|
-
if: { $ne: ['$count', 0] },
|
|
337
|
-
then: {
|
|
338
|
-
$divide: ['$unscaledCollSize', { $toDouble: '$count' }],
|
|
339
|
-
},
|
|
340
|
-
else: 0,
|
|
536
|
+
groupStage.timeseriesAvgBucketSize = {
|
|
537
|
+
$first: '$storageStats.timeseries.avgBucketSize',
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
const addFieldsStage = {
|
|
541
|
+
// `avgObjSize` is the average of per-shard `avgObjSize` weighted by `count`
|
|
542
|
+
__proto__: null,
|
|
543
|
+
avgObjSize: {
|
|
544
|
+
$cond: {
|
|
545
|
+
if: { $ne: ['$count', 0] },
|
|
546
|
+
then: {
|
|
547
|
+
$divide: ['$unscaledCollSize', { $toDouble: '$count' }],
|
|
341
548
|
},
|
|
549
|
+
else: 0,
|
|
342
550
|
},
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
const collStats = await coll
|
|
350
|
-
.aggregate([
|
|
351
|
-
{ $collStats: { storageStats: {} } },
|
|
352
|
-
{ $group: groupStage },
|
|
353
|
-
{ $addFields: addFieldsStage },
|
|
354
|
-
], { enableUtf8Validation: false })
|
|
355
|
-
.toArray();
|
|
356
|
-
if (!collStats || collStats[0] === undefined) {
|
|
357
|
-
throw new Error(`Error running $collStats aggregation stage on ${ns}`);
|
|
358
|
-
}
|
|
359
|
-
collStats[0].ns = ns;
|
|
360
|
-
return this._buildCollectionStats(databaseName, collectionName, collStats[0]);
|
|
551
|
+
},
|
|
552
|
+
};
|
|
553
|
+
// Only calculate bucket stats for time series collections
|
|
554
|
+
if (collectionType === 'timeseries') {
|
|
555
|
+
addFieldsStage.bucket_count = '$timeseriesBucketCount';
|
|
556
|
+
addFieldsStage.avg_bucket_size = '$timeseriesAvgBucketSize';
|
|
361
557
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
// server throws an error. This happens because we show collections
|
|
372
|
-
// to the user from their privileges.
|
|
373
|
-
message.includes(`Database [${databaseName}] not found`) ||
|
|
374
|
-
message.includes(`Collection [${databaseName}.${collectionName}] not found`)) {
|
|
375
|
-
return this._buildCollectionStats(databaseName, collectionName, {});
|
|
376
|
-
}
|
|
377
|
-
throw error;
|
|
558
|
+
const collStats = await coll
|
|
559
|
+
.aggregate([
|
|
560
|
+
{ $collStats: { storageStats: {} } },
|
|
561
|
+
{ $group: groupStage },
|
|
562
|
+
{ $addFields: addFieldsStage },
|
|
563
|
+
], { enableUtf8Validation: false })
|
|
564
|
+
.toArray();
|
|
565
|
+
if (!collStats || collStats[0] === undefined) {
|
|
566
|
+
throw new Error(`Error running $collStats aggregation stage on ${ns}`);
|
|
378
567
|
}
|
|
568
|
+
collStats[0].ns = ns;
|
|
569
|
+
return this._buildCollectionStats(databaseName, collectionName, collStats[0]);
|
|
379
570
|
}
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
571
|
+
catch (error) {
|
|
572
|
+
const message = error.message;
|
|
573
|
+
if (
|
|
574
|
+
// We ignore errors for fetching collStats when requesting on an
|
|
575
|
+
// unsupported collection type: either a view or a ADF
|
|
576
|
+
message.includes('not valid for Data Lake') ||
|
|
577
|
+
message.includes('is a view, not a collection') ||
|
|
578
|
+
// When trying to fetch collectionStats for a collection whose db
|
|
579
|
+
// does not exist or the collection itself does not exist, the
|
|
580
|
+
// server throws an error. This happens because we show collections
|
|
581
|
+
// to the user from their privileges.
|
|
582
|
+
message.includes(`Database [${databaseName}] not found`) ||
|
|
583
|
+
message.includes(`Collection [${databaseName}.${collectionName}] not found`)) {
|
|
584
|
+
return this._buildCollectionStats(databaseName, collectionName, {});
|
|
585
|
+
}
|
|
586
|
+
throw error;
|
|
396
587
|
}
|
|
397
|
-
|
|
398
|
-
|
|
588
|
+
}
|
|
589
|
+
async collectionInfo(dbName, collName) {
|
|
590
|
+
const [collInfo] = await this._listCollections(dbName, { name: collName });
|
|
591
|
+
return ((0, instance_detail_helper_2.adaptCollectionInfo)({
|
|
592
|
+
db: dbName,
|
|
593
|
+
...collInfo,
|
|
594
|
+
}) ?? null);
|
|
595
|
+
}
|
|
596
|
+
async killOp(id, comment) {
|
|
597
|
+
const db = this._database('admin', 'META');
|
|
598
|
+
return (0, run_command_1.runCommand)(db, { killOp: 1, id, comment }, { enableUtf8Validation: false });
|
|
599
|
+
}
|
|
600
|
+
isWritable() {
|
|
601
|
+
return this._isWritable;
|
|
602
|
+
}
|
|
603
|
+
isMongos() {
|
|
604
|
+
return this.getCurrentTopologyType() === 'Sharded';
|
|
605
|
+
}
|
|
606
|
+
getCurrentTopologyType() {
|
|
607
|
+
return this.getLastSeenTopology()?.type ?? 'Unknown';
|
|
608
|
+
}
|
|
609
|
+
async _connectionStatus() {
|
|
610
|
+
const adminDb = this._database('admin', 'META');
|
|
611
|
+
return await (0, run_command_1.runCommand)(adminDb, {
|
|
612
|
+
connectionStatus: 1,
|
|
613
|
+
showPrivileges: true,
|
|
614
|
+
}, { enableUtf8Validation: false });
|
|
615
|
+
}
|
|
616
|
+
async _getPrivilegesOrFallback(privileges = null) {
|
|
617
|
+
if (privileges) {
|
|
618
|
+
return privileges;
|
|
399
619
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
620
|
+
const { authInfo: { authenticatedUserPrivileges }, } = await this._connectionStatus();
|
|
621
|
+
return authenticatedUserPrivileges;
|
|
622
|
+
}
|
|
623
|
+
async _getRolesOrFallback(roles = null) {
|
|
624
|
+
if (roles) {
|
|
625
|
+
return roles;
|
|
406
626
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
627
|
+
const { authInfo: { authenticatedUserRoles }, } = await this._connectionStatus();
|
|
628
|
+
return authenticatedUserRoles;
|
|
629
|
+
}
|
|
630
|
+
async _listCollections(databaseName, filter = {}, { nameOnly } = {}) {
|
|
631
|
+
try {
|
|
632
|
+
const cursor = this._database(databaseName, 'CRUD').listCollections(filter, {
|
|
633
|
+
nameOnly,
|
|
634
|
+
...maybeOverrideReadPreference(this.isMongos(), this._crudClient?.readPreference),
|
|
635
|
+
});
|
|
636
|
+
// Iterate instead of using .toArray() so we can emit
|
|
637
|
+
// collection info update events as they come in.
|
|
638
|
+
const results = [];
|
|
639
|
+
for await (const result of cursor) {
|
|
640
|
+
if (!nameOnly) {
|
|
641
|
+
this._csfleCollectionTracker?.updateCollectionInfo(`${databaseName}.${result.name}`, result);
|
|
642
|
+
}
|
|
643
|
+
results.push(result);
|
|
410
644
|
}
|
|
411
|
-
|
|
412
|
-
|
|
645
|
+
return results;
|
|
646
|
+
}
|
|
647
|
+
catch (err) {
|
|
648
|
+
// Currently Compass should not fail if listCollections failed for
|
|
649
|
+
// any possible reason to preserve current behavior. We probably
|
|
650
|
+
// want this to check at least that what we got back is a server
|
|
651
|
+
// error and not a weird runtime issue on our side that can be
|
|
652
|
+
// swallowed in this case, ideally we know exactly what server
|
|
653
|
+
// errors we want to handle here and only avoid throwing in these
|
|
654
|
+
// cases
|
|
655
|
+
//
|
|
656
|
+
// TODO: https://jira.mongodb.org/browse/COMPASS-5275
|
|
657
|
+
this._logger.warn((0, logger_1.mongoLogId)(1_001_000_099), 'Failed to run listCollections', { message: err.message });
|
|
658
|
+
return [];
|
|
413
659
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
660
|
+
}
|
|
661
|
+
async listCollections(databaseName, filter = {}, { nameOnly, fetchNamespacesFromPrivileges = true, privileges = null, } = {}) {
|
|
662
|
+
const listCollections = async () => {
|
|
663
|
+
const colls = await this._listCollections(databaseName, filter, {
|
|
664
|
+
nameOnly,
|
|
665
|
+
});
|
|
666
|
+
return colls.map((coll) => ({
|
|
667
|
+
inferred_from_privileges: false,
|
|
668
|
+
...coll,
|
|
669
|
+
}));
|
|
670
|
+
};
|
|
671
|
+
const getCollectionsFromPrivileges = async () => {
|
|
672
|
+
if (!fetchNamespacesFromPrivileges) {
|
|
673
|
+
return [];
|
|
417
674
|
}
|
|
418
|
-
const
|
|
419
|
-
return
|
|
420
|
-
|
|
421
|
-
|
|
675
|
+
const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
|
|
676
|
+
return Object.keys(
|
|
677
|
+
// Privileges might not have a database we are looking for
|
|
678
|
+
databases[databaseName] || {})
|
|
679
|
+
.filter(
|
|
680
|
+
// Privileges can have collection name '' that indicates
|
|
681
|
+
// privileges on all collections in the database, we don't want
|
|
682
|
+
// those registered as "real" collection names
|
|
683
|
+
Boolean)
|
|
684
|
+
.map((name) => ({ name, inferred_from_privileges: true }));
|
|
685
|
+
};
|
|
686
|
+
const [listedCollections, collectionsFromPrivileges] = await Promise.all([
|
|
687
|
+
listCollections(),
|
|
688
|
+
// If the filter is not empty, we can't meaningfully derive collections
|
|
689
|
+
// from privileges and filter them as the criteria might include any key
|
|
690
|
+
// from the listCollections result object and there is no such info in
|
|
691
|
+
// privileges. Because of that we are ignoring privileges completely if
|
|
692
|
+
// listCollections was called with a filter.
|
|
693
|
+
isEmptyObject(filter) ? getCollectionsFromPrivileges() : [],
|
|
694
|
+
]);
|
|
695
|
+
const collections = uniqueBy(
|
|
696
|
+
// NB: Order is important, we want listed collections to take precedence
|
|
697
|
+
// if they were fetched successfully
|
|
698
|
+
[...collectionsFromPrivileges, ...listedCollections], 'name').map(({ inferred_from_privileges, ...coll }) => ({
|
|
699
|
+
inferred_from_privileges,
|
|
700
|
+
...(0, instance_detail_helper_2.adaptCollectionInfo)({ db: databaseName, ...coll }),
|
|
701
|
+
}));
|
|
702
|
+
return collections;
|
|
703
|
+
}
|
|
704
|
+
async listDatabases({ nameOnly, fetchNamespacesFromPrivileges = true, privileges = null, roles = null, } = {}) {
|
|
705
|
+
const adminDb = this._database('admin', 'CRUD');
|
|
706
|
+
const listDatabases = async () => {
|
|
422
707
|
try {
|
|
423
|
-
const
|
|
708
|
+
const { databases } = await (0, run_command_1.runCommand)(adminDb, {
|
|
709
|
+
listDatabases: 1,
|
|
424
710
|
nameOnly,
|
|
711
|
+
}, {
|
|
712
|
+
enableUtf8Validation: false,
|
|
425
713
|
...maybeOverrideReadPreference(this.isMongos(), this._crudClient?.readPreference),
|
|
426
714
|
});
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if (!nameOnly) {
|
|
432
|
-
this._csfleCollectionTracker?.updateCollectionInfo(`${databaseName}.${result.name}`, result);
|
|
433
|
-
}
|
|
434
|
-
results.push(result);
|
|
435
|
-
}
|
|
436
|
-
return results;
|
|
715
|
+
return databases.map((x) => ({
|
|
716
|
+
...x,
|
|
717
|
+
inferred_from_privileges: false,
|
|
718
|
+
}));
|
|
437
719
|
}
|
|
438
720
|
catch (err) {
|
|
439
|
-
// Currently Compass should not fail if
|
|
440
|
-
//
|
|
441
|
-
//
|
|
442
|
-
//
|
|
443
|
-
//
|
|
444
|
-
//
|
|
445
|
-
// cases
|
|
721
|
+
// Currently Compass should not fail if listDatabase failed for any
|
|
722
|
+
// possible reason to preserve current behavior. We probably want this
|
|
723
|
+
// to check at least that what we got back is a server error and not a
|
|
724
|
+
// weird runtime issue on our side that can be swallowed in this case,
|
|
725
|
+
// ideally we know exactly what server errors we want to handle here
|
|
726
|
+
// and only avoid throwing in these cases
|
|
446
727
|
//
|
|
447
728
|
// TODO: https://jira.mongodb.org/browse/COMPASS-5275
|
|
448
|
-
this._logger.warn((0, logger_1.mongoLogId)(
|
|
729
|
+
this._logger.warn((0, logger_1.mongoLogId)(1_001_000_098), 'Failed to run listDatabases', { message: err.message });
|
|
449
730
|
return [];
|
|
450
731
|
}
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
// If the filter is not empty, we can't meaningfully derive collections
|
|
480
|
-
// from privileges and filter them as the criteria might include any key
|
|
481
|
-
// from the listCollections result object and there is no such info in
|
|
482
|
-
// privileges. Because of that we are ignoring privileges completely if
|
|
483
|
-
// listCollections was called with a filter.
|
|
484
|
-
isEmptyObject(filter) ? getCollectionsFromPrivileges() : [],
|
|
485
|
-
]);
|
|
486
|
-
const collections = uniqueBy(
|
|
487
|
-
// NB: Order is important, we want listed collections to take precedence
|
|
488
|
-
// if they were fetched successfully
|
|
489
|
-
[...collectionsFromPrivileges, ...listedCollections], 'name').map(({ inferred_from_privileges, ...coll }) => ({
|
|
490
|
-
inferred_from_privileges,
|
|
491
|
-
...(0, instance_detail_helper_2.adaptCollectionInfo)({ db: databaseName, ...coll }),
|
|
732
|
+
};
|
|
733
|
+
const getDatabasesFromPrivileges = async () => {
|
|
734
|
+
if (!fetchNamespacesFromPrivileges) {
|
|
735
|
+
return [];
|
|
736
|
+
}
|
|
737
|
+
const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
|
|
738
|
+
return Object.keys(databases)
|
|
739
|
+
.filter(
|
|
740
|
+
// For the roles created in admin database, the database name
|
|
741
|
+
// can be '' meaning that it applies to all databases. We can't
|
|
742
|
+
// meaningfully handle this in the UI so we are filtering these
|
|
743
|
+
// out
|
|
744
|
+
Boolean)
|
|
745
|
+
.map((name) => ({ name, inferred_from_privileges: true }));
|
|
746
|
+
};
|
|
747
|
+
const getDatabasesFromRoles = async () => {
|
|
748
|
+
const databases = (0, instance_detail_helper_2.getDatabasesByRoles)(await this._getRolesOrFallback(roles),
|
|
749
|
+
// https://jira.mongodb.org/browse/HELP-32199
|
|
750
|
+
// Atlas shared tier MongoDB server version v5+ does not return
|
|
751
|
+
// `authenticatedUserPrivileges` as part of the `connectionStatus`.
|
|
752
|
+
// As a workaround we show the databases the user has
|
|
753
|
+
// certain general built-in roles for.
|
|
754
|
+
// This does not cover custom user roles which can
|
|
755
|
+
// have custom privileges that we can't currently fetch.
|
|
756
|
+
['read', 'readWrite', 'dbAdmin', 'dbOwner']);
|
|
757
|
+
return databases.map((name) => ({
|
|
758
|
+
name,
|
|
759
|
+
inferred_from_privileges: true,
|
|
492
760
|
}));
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
inferred_from_privileges: false,
|
|
509
|
-
}));
|
|
510
|
-
}
|
|
511
|
-
catch (err) {
|
|
512
|
-
// Currently Compass should not fail if listDatabase failed for any
|
|
513
|
-
// possible reason to preserve current behavior. We probably want this
|
|
514
|
-
// to check at least that what we got back is a server error and not a
|
|
515
|
-
// weird runtime issue on our side that can be swallowed in this case,
|
|
516
|
-
// ideally we know exactly what server errors we want to handle here
|
|
517
|
-
// and only avoid throwing in these cases
|
|
518
|
-
//
|
|
519
|
-
// TODO: https://jira.mongodb.org/browse/COMPASS-5275
|
|
520
|
-
this._logger.warn((0, logger_1.mongoLogId)(1_001_000_098), 'Failed to run listDatabases', { message: err.message });
|
|
521
|
-
return [];
|
|
522
|
-
}
|
|
523
|
-
};
|
|
524
|
-
const getDatabasesFromPrivileges = async () => {
|
|
525
|
-
if (!fetchNamespacesFromPrivileges) {
|
|
526
|
-
return [];
|
|
527
|
-
}
|
|
528
|
-
const databases = (0, instance_detail_helper_2.getPrivilegesByDatabaseAndCollection)(await this._getPrivilegesOrFallback(privileges), ['find']);
|
|
529
|
-
return Object.keys(databases)
|
|
530
|
-
.filter(
|
|
531
|
-
// For the roles created in admin database, the database name
|
|
532
|
-
// can be '' meaning that it applies to all databases. We can't
|
|
533
|
-
// meaningfully handle this in the UI so we are filtering these
|
|
534
|
-
// out
|
|
535
|
-
Boolean)
|
|
536
|
-
.map((name) => ({ name, inferred_from_privileges: true }));
|
|
537
|
-
};
|
|
538
|
-
const getDatabasesFromRoles = async () => {
|
|
539
|
-
const databases = (0, instance_detail_helper_2.getDatabasesByRoles)(await this._getRolesOrFallback(roles),
|
|
540
|
-
// https://jira.mongodb.org/browse/HELP-32199
|
|
541
|
-
// Atlas shared tier MongoDB server version v5+ does not return
|
|
542
|
-
// `authenticatedUserPrivileges` as part of the `connectionStatus`.
|
|
543
|
-
// As a workaround we show the databases the user has
|
|
544
|
-
// certain general built-in roles for.
|
|
545
|
-
// This does not cover custom user roles which can
|
|
546
|
-
// have custom privileges that we can't currently fetch.
|
|
547
|
-
['read', 'readWrite', 'dbAdmin', 'dbOwner']);
|
|
548
|
-
return databases.map((name) => ({
|
|
549
|
-
name,
|
|
550
|
-
inferred_from_privileges: true,
|
|
551
|
-
}));
|
|
761
|
+
};
|
|
762
|
+
const [listedDatabases, databasesFromPrivileges, databasesFromRoles] = await Promise.all([
|
|
763
|
+
listDatabases(),
|
|
764
|
+
getDatabasesFromPrivileges(),
|
|
765
|
+
getDatabasesFromRoles(),
|
|
766
|
+
]);
|
|
767
|
+
const databases = uniqueBy(
|
|
768
|
+
// NB: Order is important, we want listed collections to take precedence
|
|
769
|
+
// if they were fetched successfully
|
|
770
|
+
[...databasesFromRoles, ...databasesFromPrivileges, ...listedDatabases], 'name').map(({ name, inferred_from_privileges, ...db }) => {
|
|
771
|
+
return {
|
|
772
|
+
_id: name,
|
|
773
|
+
name,
|
|
774
|
+
inferred_from_privileges,
|
|
775
|
+
...(0, instance_detail_helper_2.adaptDatabaseInfo)(db),
|
|
552
776
|
};
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
...(0, instance_detail_helper_2.adaptDatabaseInfo)(db),
|
|
567
|
-
};
|
|
568
|
-
});
|
|
569
|
-
return databases;
|
|
570
|
-
}
|
|
571
|
-
addReauthenticationHandler(handler) {
|
|
572
|
-
this._reauthenticationHandlers.add(handler);
|
|
777
|
+
});
|
|
778
|
+
return databases;
|
|
779
|
+
}
|
|
780
|
+
addReauthenticationHandler(handler) {
|
|
781
|
+
this._reauthenticationHandlers.add(handler);
|
|
782
|
+
}
|
|
783
|
+
async _requestReauthenticationFromUser() {
|
|
784
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_194), 'Requesting re-authentication from user');
|
|
785
|
+
let threw = true;
|
|
786
|
+
try {
|
|
787
|
+
for (const handler of this._reauthenticationHandlers)
|
|
788
|
+
await handler();
|
|
789
|
+
threw = false;
|
|
573
790
|
}
|
|
574
|
-
|
|
575
|
-
this._logger.info((0, logger_1.mongoLogId)(
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
for (const handler of this._reauthenticationHandlers)
|
|
579
|
-
await handler();
|
|
580
|
-
threw = false;
|
|
581
|
-
}
|
|
582
|
-
finally {
|
|
583
|
-
this._logger.info((0, logger_1.mongoLogId)(1_001_000_193), 'Completed re-authentication request', {
|
|
584
|
-
wantsReauth: !threw,
|
|
585
|
-
});
|
|
586
|
-
}
|
|
791
|
+
finally {
|
|
792
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_193), 'Completed re-authentication request', {
|
|
793
|
+
wantsReauth: !threw,
|
|
794
|
+
});
|
|
587
795
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
796
|
+
}
|
|
797
|
+
async connect({ signal, productName, productDocsLink, } = {}) {
|
|
798
|
+
if (this._metadataClient) {
|
|
799
|
+
(0, logger_1.debug)('already connected');
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
if (this._isConnecting) {
|
|
803
|
+
(0, logger_1.debug)('connect method called more than once');
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
(0, logger_1.debug)('connecting...');
|
|
807
|
+
this._isConnecting = true;
|
|
808
|
+
const clusterName = this._connectionOptions.lookup?.().clusterName;
|
|
809
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_014), 'Connecting Started', {
|
|
810
|
+
connectionId: this._id,
|
|
811
|
+
url: (0, redact_1.redactConnectionString)(this._connectionOptions.connectionString),
|
|
812
|
+
csfle: this._csfleLogInformation(this._connectionOptions.fleOptions),
|
|
813
|
+
...(clusterName && { clusterName }),
|
|
814
|
+
});
|
|
815
|
+
try {
|
|
816
|
+
const [metadataClient, crudClient, tunnel, state, connectionOptions] = await (0, connect_mongo_client_1.connectMongoClientDataService)({
|
|
817
|
+
connectionOptions: this._connectionOptions,
|
|
818
|
+
proxyOptions: this._proxyOptions,
|
|
819
|
+
setupListeners: this._setupListeners.bind(this),
|
|
820
|
+
signal,
|
|
821
|
+
logger: this._unboundLogger,
|
|
822
|
+
productName,
|
|
823
|
+
productDocsLink,
|
|
824
|
+
reauthenticationHandler: this._requestReauthenticationFromUser.bind(this),
|
|
825
|
+
});
|
|
826
|
+
const attr = {
|
|
601
827
|
connectionId: this._id,
|
|
602
|
-
|
|
603
|
-
|
|
828
|
+
isWritable: this.isWritable(),
|
|
829
|
+
isMongos: this.isMongos(),
|
|
604
830
|
...(clusterName && { clusterName }),
|
|
831
|
+
};
|
|
832
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_015), 'Connecting Succeeded', attr);
|
|
833
|
+
(0, logger_1.debug)('connected!', attr);
|
|
834
|
+
state.oidcPlugin.logger.on('mongodb-oidc-plugin:state-updated', () => {
|
|
835
|
+
this._emitter.emit('connectionInfoSecretsChanged');
|
|
605
836
|
});
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
reauthenticationHandler: this._requestReauthenticationFromUser.bind(this),
|
|
616
|
-
});
|
|
617
|
-
const attr = {
|
|
618
|
-
connectionId: this._id,
|
|
619
|
-
isWritable: this.isWritable(),
|
|
620
|
-
isMongos: this.isMongos(),
|
|
621
|
-
...(clusterName && { clusterName }),
|
|
622
|
-
};
|
|
623
|
-
this._logger.info((0, logger_1.mongoLogId)(1_001_000_015), 'Connecting Succeeded', attr);
|
|
624
|
-
(0, logger_1.debug)('connected!', attr);
|
|
625
|
-
state.oidcPlugin.logger.on('mongodb-oidc-plugin:state-updated', () => {
|
|
626
|
-
this._emitter.emit('connectionInfoSecretsChanged');
|
|
627
|
-
});
|
|
628
|
-
state.oidcPlugin.logger.on('mongodb-oidc-plugin:auth-failed', ({ error }) => {
|
|
629
|
-
this._emitter.emit('oidcAuthFailed', error);
|
|
630
|
-
});
|
|
631
|
-
this._metadataClient = metadataClient;
|
|
632
|
-
this._crudClient = crudClient;
|
|
633
|
-
this._tunnel = tunnel;
|
|
634
|
-
this._state = state;
|
|
635
|
-
this._mongoClientConnectionOptions = connectionOptions;
|
|
636
|
-
this._csfleCollectionTracker = new csfle_collection_tracker_1.CSFLECollectionTrackerImpl(this, this._crudClient);
|
|
637
|
-
}
|
|
638
|
-
catch (error) {
|
|
639
|
-
this._logger.info((0, logger_1.mongoLogId)(1_001_000_359), 'Connecting Failed', {
|
|
640
|
-
connectionId: this._id,
|
|
641
|
-
error: error && typeof error === 'object' && 'message' in error
|
|
642
|
-
? error?.message
|
|
643
|
-
: 'unknown error',
|
|
644
|
-
...(clusterName && { clusterName }),
|
|
645
|
-
});
|
|
646
|
-
throw error;
|
|
647
|
-
}
|
|
648
|
-
finally {
|
|
649
|
-
this._isConnecting = false;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
estimatedCount(ns, options = {}, executionOptions) {
|
|
653
|
-
const maxTimeMS = options.maxTimeMS ?? 500;
|
|
654
|
-
return this._cancellableOperation(async (session) => {
|
|
655
|
-
return this._collection(ns, 'CRUD').estimatedDocumentCount({
|
|
656
|
-
...options,
|
|
657
|
-
maxTimeMS,
|
|
658
|
-
session,
|
|
659
|
-
});
|
|
660
|
-
}, (session) => session.endSession(), executionOptions?.abortSignal);
|
|
661
|
-
}
|
|
662
|
-
count(ns, filter, options = {}, executionOptions) {
|
|
663
|
-
return this._cancellableOperation(async (session) => {
|
|
664
|
-
return this._collection(ns, 'CRUD').countDocuments(filter, {
|
|
665
|
-
...this._getOptionsWithFallbackReadPreference(options, executionOptions),
|
|
666
|
-
session,
|
|
667
|
-
});
|
|
668
|
-
}, (session) => session.endSession(), executionOptions?.abortSignal);
|
|
669
|
-
}
|
|
670
|
-
async createCollection(ns, options) {
|
|
671
|
-
const collectionName = this._collectionName(ns);
|
|
672
|
-
const db = this._database(ns, 'CRUD');
|
|
673
|
-
return await db.createCollection(collectionName, options);
|
|
674
|
-
}
|
|
675
|
-
async createIndex(ns, spec, options) {
|
|
676
|
-
const coll = this._collection(ns, 'CRUD');
|
|
677
|
-
return await coll.createIndex(spec, options);
|
|
678
|
-
}
|
|
679
|
-
async deleteOne(ns, filter, options) {
|
|
680
|
-
const coll = this._collection(ns, 'CRUD');
|
|
681
|
-
return await coll.deleteOne(filter, options);
|
|
837
|
+
state.oidcPlugin.logger.on('mongodb-oidc-plugin:auth-failed', ({ error }) => {
|
|
838
|
+
this._emitter.emit('oidcAuthFailed', error);
|
|
839
|
+
});
|
|
840
|
+
this._metadataClient = metadataClient;
|
|
841
|
+
this._crudClient = crudClient;
|
|
842
|
+
this._tunnel = tunnel;
|
|
843
|
+
this._state = state;
|
|
844
|
+
this._mongoClientConnectionOptions = connectionOptions;
|
|
845
|
+
this._csfleCollectionTracker = new csfle_collection_tracker_1.CSFLECollectionTrackerImpl(this, this._crudClient);
|
|
682
846
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
847
|
+
catch (error) {
|
|
848
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_359), 'Connecting Failed', {
|
|
849
|
+
connectionId: this._id,
|
|
850
|
+
error: error && typeof error === 'object' && 'message' in error
|
|
851
|
+
? error?.message
|
|
852
|
+
: 'unknown error',
|
|
853
|
+
...(clusterName && { clusterName }),
|
|
854
|
+
});
|
|
855
|
+
throw error;
|
|
686
856
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
return await coll.updateMany(filter, update, options);
|
|
857
|
+
finally {
|
|
858
|
+
this._isConnecting = false;
|
|
690
859
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
860
|
+
}
|
|
861
|
+
estimatedCount(ns, options = {}, executionOptions) {
|
|
862
|
+
const maxTimeMS = options.maxTimeMS ?? 500;
|
|
863
|
+
return this._cancellableOperation(async (session) => {
|
|
864
|
+
return this._collection(ns, 'CRUD').estimatedDocumentCount({
|
|
865
|
+
...options,
|
|
866
|
+
maxTimeMS,
|
|
867
|
+
session,
|
|
868
|
+
});
|
|
869
|
+
}, (session) => session.endSession(), executionOptions?.abortSignal);
|
|
870
|
+
}
|
|
871
|
+
count(ns, filter, options = {}, executionOptions) {
|
|
872
|
+
return this._cancellableOperation(async (session) => {
|
|
873
|
+
return this._collection(ns, 'CRUD').countDocuments(filter, {
|
|
874
|
+
...this._getOptionsWithFallbackReadPreference(options, executionOptions),
|
|
875
|
+
session,
|
|
876
|
+
});
|
|
877
|
+
}, (session) => session.endSession(), executionOptions?.abortSignal);
|
|
878
|
+
}
|
|
879
|
+
async createCollection(ns, options) {
|
|
880
|
+
const collectionName = this._collectionName(ns);
|
|
881
|
+
const db = this._database(ns, 'CRUD');
|
|
882
|
+
return await db.createCollection(collectionName, options);
|
|
883
|
+
}
|
|
884
|
+
async createIndex(ns, spec, options) {
|
|
885
|
+
const coll = this._collection(ns, 'CRUD');
|
|
886
|
+
return await coll.createIndex(spec, options);
|
|
887
|
+
}
|
|
888
|
+
async deleteOne(ns, filter, options) {
|
|
889
|
+
const coll = this._collection(ns, 'CRUD');
|
|
890
|
+
return await coll.deleteOne(filter, options);
|
|
891
|
+
}
|
|
892
|
+
async deleteMany(ns, filter, options) {
|
|
893
|
+
const coll = this._collection(ns, 'CRUD');
|
|
894
|
+
return await coll.deleteMany(filter, options);
|
|
895
|
+
}
|
|
896
|
+
async updateMany(ns, filter, update, options) {
|
|
897
|
+
const coll = this._collection(ns, 'CRUD');
|
|
898
|
+
return await coll.updateMany(filter, update, options);
|
|
899
|
+
}
|
|
900
|
+
async disconnect() {
|
|
901
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_016), 'Disconnecting');
|
|
902
|
+
try {
|
|
903
|
+
await Promise.all([
|
|
904
|
+
this._metadataClient
|
|
905
|
+
?.close(true)
|
|
906
|
+
.catch((err) => (0, logger_1.debug)('failed to close MongoClient', err)),
|
|
907
|
+
this._crudClient !== this._metadataClient &&
|
|
908
|
+
this._crudClient
|
|
696
909
|
?.close(true)
|
|
697
910
|
.catch((err) => (0, logger_1.debug)('failed to close MongoClient', err)),
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
this._state
|
|
706
|
-
?.destroy()
|
|
707
|
-
.catch((err) => (0, logger_1.debug)('failed to destroy DevtoolsConnectionState', err)),
|
|
708
|
-
]);
|
|
709
|
-
}
|
|
710
|
-
finally {
|
|
711
|
-
this._cleanup();
|
|
712
|
-
this._logger.info((0, logger_1.mongoLogId)(1_001_000_017), 'Fully closed');
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
async dropCollection(ns) {
|
|
716
|
-
const db = this._database(ns, 'CRUD');
|
|
717
|
-
const collName = this._collectionName(ns);
|
|
718
|
-
const coll = db.collection(collName);
|
|
719
|
-
let result = null;
|
|
720
|
-
try {
|
|
721
|
-
[result] = await db
|
|
722
|
-
.listCollections({ name: collName }, { nameOnly: false })
|
|
723
|
-
.toArray();
|
|
724
|
-
}
|
|
725
|
-
catch {
|
|
726
|
-
// ignore
|
|
727
|
-
}
|
|
728
|
-
const options = {};
|
|
729
|
-
const encryptedFieldsInfo = result?.options?.encryptedFields;
|
|
730
|
-
if (encryptedFieldsInfo) {
|
|
731
|
-
options.encryptedFields = encryptedFieldsInfo;
|
|
732
|
-
}
|
|
733
|
-
return await coll.drop(options);
|
|
734
|
-
}
|
|
735
|
-
renameCollection(ns, newCollectionName) {
|
|
736
|
-
const db = this._database(ns, 'META');
|
|
737
|
-
return db.renameCollection(this._collectionName(ns), newCollectionName);
|
|
738
|
-
}
|
|
739
|
-
async dropDatabase(name) {
|
|
740
|
-
const db = this._database(name, 'CRUD');
|
|
741
|
-
return await db.dropDatabase();
|
|
742
|
-
}
|
|
743
|
-
async dropIndex(ns, name) {
|
|
744
|
-
const coll = this._collection(ns, 'CRUD');
|
|
745
|
-
return await coll.dropIndex(name);
|
|
746
|
-
}
|
|
747
|
-
async isListSearchIndexesSupported(ns) {
|
|
748
|
-
try {
|
|
749
|
-
await this.getSearchIndexes(ns);
|
|
750
|
-
}
|
|
751
|
-
catch {
|
|
752
|
-
return false;
|
|
753
|
-
}
|
|
754
|
-
return true;
|
|
755
|
-
}
|
|
756
|
-
async getSearchIndexes(ns) {
|
|
757
|
-
const coll = this._collection(ns, 'CRUD');
|
|
758
|
-
const cursor = coll.listSearchIndexes();
|
|
759
|
-
const indexes = await cursor.toArray();
|
|
760
|
-
void cursor.close();
|
|
761
|
-
return indexes;
|
|
762
|
-
}
|
|
763
|
-
async createSearchIndex(ns, description) {
|
|
764
|
-
const coll = this._collection(ns, 'CRUD');
|
|
765
|
-
return coll.createSearchIndex(description);
|
|
766
|
-
}
|
|
767
|
-
async updateSearchIndex(ns, name, definition) {
|
|
768
|
-
const coll = this._collection(ns, 'CRUD');
|
|
769
|
-
return coll.updateSearchIndex(name, definition);
|
|
770
|
-
}
|
|
771
|
-
async dropSearchIndex(ns, name) {
|
|
772
|
-
const coll = this._collection(ns, 'CRUD');
|
|
773
|
-
return coll.dropSearchIndex(name);
|
|
774
|
-
}
|
|
775
|
-
aggregateCursor(ns, pipeline, options = {}) {
|
|
776
|
-
return this._collection(ns, 'CRUD').aggregate(pipeline, options);
|
|
777
|
-
}
|
|
778
|
-
// @ts-expect-error generic in the method trips up TS here resulting in
|
|
779
|
-
// Promise<unknown> is not assignable to Promise<Document[]>
|
|
780
|
-
aggregate(ns, pipeline, options = {}, executionOptions) {
|
|
781
|
-
let cursor;
|
|
782
|
-
return this._cancellableOperation(async (session) => {
|
|
783
|
-
cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
|
|
784
|
-
...options,
|
|
785
|
-
session,
|
|
786
|
-
});
|
|
787
|
-
const results = await cursor.toArray();
|
|
788
|
-
void cursor.close();
|
|
789
|
-
return results;
|
|
790
|
-
}, () => cursor?.close(), executionOptions?.abortSignal);
|
|
791
|
-
}
|
|
792
|
-
find(ns, filter, options = {}, executionOptions) {
|
|
793
|
-
let cursor;
|
|
794
|
-
return this._cancellableOperation(async (session) => {
|
|
795
|
-
cursor = this._collection(ns, 'CRUD').find(filter, {
|
|
796
|
-
...options,
|
|
797
|
-
session,
|
|
798
|
-
});
|
|
799
|
-
const results = await cursor.toArray();
|
|
800
|
-
void cursor.close();
|
|
801
|
-
return results;
|
|
802
|
-
}, () => cursor?.close(), executionOptions?.abortSignal);
|
|
803
|
-
}
|
|
804
|
-
findCursor(ns, filter, options = {}) {
|
|
805
|
-
return this._collection(ns, 'CRUD').find(filter, options);
|
|
911
|
+
this._tunnel
|
|
912
|
+
?.close()
|
|
913
|
+
.catch((err) => (0, logger_1.debug)('failed to close tunnel', err)),
|
|
914
|
+
this._state
|
|
915
|
+
?.destroy()
|
|
916
|
+
.catch((err) => (0, logger_1.debug)('failed to destroy DevtoolsConnectionState', err)),
|
|
917
|
+
]);
|
|
806
918
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
919
|
+
finally {
|
|
920
|
+
this._cleanup();
|
|
921
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_017), 'Fully closed');
|
|
810
922
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
923
|
+
}
|
|
924
|
+
async dropCollection(ns) {
|
|
925
|
+
const db = this._database(ns, 'CRUD');
|
|
926
|
+
const collName = this._collectionName(ns);
|
|
927
|
+
const coll = db.collection(collName);
|
|
928
|
+
let result = null;
|
|
929
|
+
try {
|
|
930
|
+
[result] = await db
|
|
931
|
+
.listCollections({ name: collName }, { nameOnly: false })
|
|
932
|
+
.toArray();
|
|
814
933
|
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
return await coll.updateOne(filter, update, options);
|
|
934
|
+
catch {
|
|
935
|
+
// ignore
|
|
818
936
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
937
|
+
const options = {};
|
|
938
|
+
const encryptedFieldsInfo = result?.options?.encryptedFields;
|
|
939
|
+
if (encryptedFieldsInfo) {
|
|
940
|
+
options.encryptedFields = encryptedFieldsInfo;
|
|
822
941
|
}
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
942
|
+
return await coll.drop(options);
|
|
943
|
+
}
|
|
944
|
+
renameCollection(ns, newCollectionName) {
|
|
945
|
+
const db = this._database(ns, 'META');
|
|
946
|
+
return db.renameCollection(this._collectionName(ns), newCollectionName);
|
|
947
|
+
}
|
|
948
|
+
async dropDatabase(name) {
|
|
949
|
+
const db = this._database(name, 'CRUD');
|
|
950
|
+
return await db.dropDatabase();
|
|
951
|
+
}
|
|
952
|
+
async dropIndex(ns, name) {
|
|
953
|
+
const coll = this._collection(ns, 'CRUD');
|
|
954
|
+
return await coll.dropIndex(name);
|
|
955
|
+
}
|
|
956
|
+
async isListSearchIndexesSupported(ns) {
|
|
957
|
+
try {
|
|
958
|
+
await this.getSearchIndexes(ns);
|
|
838
959
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
let cursor;
|
|
842
|
-
return this._cancellableOperation(async (session) => {
|
|
843
|
-
cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
|
|
844
|
-
...options,
|
|
845
|
-
session,
|
|
846
|
-
});
|
|
847
|
-
const results = await cursor.explain({
|
|
848
|
-
verbosity,
|
|
849
|
-
maxTimeMS: executionOptions?.maxTimeMS,
|
|
850
|
-
});
|
|
851
|
-
void cursor.close();
|
|
852
|
-
return results;
|
|
853
|
-
}, () => cursor?.close(), executionOptions?.abortSignal);
|
|
960
|
+
catch {
|
|
961
|
+
return false;
|
|
854
962
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
963
|
+
return true;
|
|
964
|
+
}
|
|
965
|
+
async getSearchIndexes(ns) {
|
|
966
|
+
const coll = this._collection(ns, 'CRUD');
|
|
967
|
+
const cursor = coll.listSearchIndexes();
|
|
968
|
+
const indexes = await cursor.toArray();
|
|
969
|
+
void cursor.close();
|
|
970
|
+
return indexes;
|
|
971
|
+
}
|
|
972
|
+
async createSearchIndex(ns, description) {
|
|
973
|
+
const coll = this._collection(ns, 'CRUD');
|
|
974
|
+
return coll.createSearchIndex(description);
|
|
975
|
+
}
|
|
976
|
+
async updateSearchIndex(ns, name, definition) {
|
|
977
|
+
const coll = this._collection(ns, 'CRUD');
|
|
978
|
+
return coll.updateSearchIndex(name, definition);
|
|
979
|
+
}
|
|
980
|
+
async dropSearchIndex(ns, name) {
|
|
981
|
+
const coll = this._collection(ns, 'CRUD');
|
|
982
|
+
return coll.dropSearchIndex(name);
|
|
983
|
+
}
|
|
984
|
+
aggregateCursor(ns, pipeline, options = {}) {
|
|
985
|
+
return this._collection(ns, 'CRUD').aggregate(pipeline, options);
|
|
986
|
+
}
|
|
987
|
+
// @ts-expect-error generic in the method trips up TS here resulting in
|
|
988
|
+
// Promise<unknown> is not assignable to Promise<Document[]>
|
|
989
|
+
aggregate(ns, pipeline, options = {}, executionOptions) {
|
|
990
|
+
let cursor;
|
|
991
|
+
return this._cancellableOperation(async (session) => {
|
|
992
|
+
cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
|
|
993
|
+
...options,
|
|
994
|
+
session,
|
|
995
|
+
});
|
|
996
|
+
const results = await cursor.toArray();
|
|
997
|
+
void cursor.close();
|
|
998
|
+
return results;
|
|
999
|
+
}, () => cursor?.close(), executionOptions?.abortSignal);
|
|
1000
|
+
}
|
|
1001
|
+
find(ns, filter, options = {}, executionOptions) {
|
|
1002
|
+
let cursor;
|
|
1003
|
+
return this._cancellableOperation(async (session) => {
|
|
1004
|
+
cursor = this._collection(ns, 'CRUD').find(filter, {
|
|
1005
|
+
...options,
|
|
1006
|
+
session,
|
|
1007
|
+
});
|
|
1008
|
+
const results = await cursor.toArray();
|
|
1009
|
+
void cursor.close();
|
|
1010
|
+
return results;
|
|
1011
|
+
}, () => cursor?.close(), executionOptions?.abortSignal);
|
|
1012
|
+
}
|
|
1013
|
+
findCursor(ns, filter, options = {}) {
|
|
1014
|
+
return this._collection(ns, 'CRUD').find(filter, options);
|
|
1015
|
+
}
|
|
1016
|
+
async findOneAndReplace(ns, filter, replacement, options) {
|
|
1017
|
+
const coll = this._collection(ns, 'CRUD');
|
|
1018
|
+
return await coll.findOneAndReplace(filter, replacement, options);
|
|
1019
|
+
}
|
|
1020
|
+
async findOneAndUpdate(ns, filter, update, options) {
|
|
1021
|
+
const coll = this._collection(ns, 'CRUD');
|
|
1022
|
+
return await coll.findOneAndUpdate(filter, update, options);
|
|
1023
|
+
}
|
|
1024
|
+
async updateOne(ns, filter, update, options) {
|
|
1025
|
+
const coll = this._collection(ns, 'CRUD');
|
|
1026
|
+
return await coll.updateOne(filter, update, options);
|
|
1027
|
+
}
|
|
1028
|
+
async replaceOne(ns, filter, replacement, options) {
|
|
1029
|
+
const coll = this._collection(ns, 'CRUD');
|
|
1030
|
+
return await coll.replaceOne(filter, replacement, options);
|
|
1031
|
+
}
|
|
1032
|
+
explainFind(ns, filter, options = {}, executionOptions) {
|
|
1033
|
+
const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats;
|
|
1034
|
+
let cursor;
|
|
1035
|
+
return this._cancellableOperation(async (session) => {
|
|
1036
|
+
cursor = this._collection(ns, 'CRUD').find(filter, {
|
|
1037
|
+
...options,
|
|
1038
|
+
session,
|
|
1039
|
+
});
|
|
1040
|
+
const results = await cursor.explain({
|
|
1041
|
+
verbosity,
|
|
1042
|
+
maxTimeMS: executionOptions?.maxTimeMS,
|
|
1043
|
+
});
|
|
1044
|
+
void cursor.close();
|
|
1045
|
+
return results;
|
|
1046
|
+
}, () => cursor?.close(), executionOptions?.abortSignal);
|
|
1047
|
+
}
|
|
1048
|
+
explainAggregate(ns, pipeline, options, executionOptions) {
|
|
1049
|
+
const verbosity = executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats;
|
|
1050
|
+
let cursor;
|
|
1051
|
+
return this._cancellableOperation(async (session) => {
|
|
1052
|
+
cursor = this._collection(ns, 'CRUD').aggregate(pipeline, {
|
|
1053
|
+
...options,
|
|
1054
|
+
session,
|
|
1055
|
+
});
|
|
1056
|
+
const results = await cursor.explain({
|
|
1057
|
+
verbosity,
|
|
1058
|
+
maxTimeMS: executionOptions?.maxTimeMS,
|
|
1059
|
+
});
|
|
1060
|
+
void cursor.close();
|
|
1061
|
+
return results;
|
|
1062
|
+
}, () => cursor?.close(), executionOptions?.abortSignal);
|
|
1063
|
+
}
|
|
1064
|
+
async _indexStats(ns) {
|
|
1065
|
+
try {
|
|
1066
|
+
const stats = await this.aggregate(ns, [
|
|
1067
|
+
{ $indexStats: {} },
|
|
1068
|
+
{
|
|
1069
|
+
$project: {
|
|
1070
|
+
name: 1,
|
|
1071
|
+
usageHost: '$host',
|
|
1072
|
+
usageCount: '$accesses.ops',
|
|
1073
|
+
usageSince: '$accesses.since',
|
|
866
1074
|
},
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
}
|
|
872
|
-
catch (err) {
|
|
873
|
-
if ((0, instance_detail_helper_1.isNotAuthorized)(err) || (0, instance_detail_helper_1.isNotSupportedPipelineStage)(err)) {
|
|
874
|
-
return {};
|
|
875
|
-
}
|
|
876
|
-
throw err;
|
|
877
|
-
}
|
|
1075
|
+
},
|
|
1076
|
+
]);
|
|
1077
|
+
return Object.fromEntries(stats.map((index) => {
|
|
1078
|
+
return [index.name, index];
|
|
1079
|
+
}));
|
|
878
1080
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
const aggResult = (await coll
|
|
883
|
-
.aggregate([
|
|
884
|
-
{ $collStats: { storageStats: {} } },
|
|
885
|
-
{
|
|
886
|
-
$project: {
|
|
887
|
-
indexSizes: { $objectToArray: '$storageStats.indexSizes' },
|
|
888
|
-
},
|
|
889
|
-
},
|
|
890
|
-
{ $unwind: '$indexSizes' },
|
|
891
|
-
{
|
|
892
|
-
$group: {
|
|
893
|
-
_id: '$indexSizes.k',
|
|
894
|
-
size: { $sum: { $toDouble: '$indexSizes.v' } },
|
|
895
|
-
},
|
|
896
|
-
},
|
|
897
|
-
])
|
|
898
|
-
.toArray());
|
|
899
|
-
return Object.fromEntries(aggResult.map(({ _id, size }) => [_id, size]));
|
|
900
|
-
}
|
|
901
|
-
catch (err) {
|
|
902
|
-
if ((0, instance_detail_helper_1.isNotAuthorized)(err) || (0, instance_detail_helper_1.isNotSupportedPipelineStage)(err)) {
|
|
903
|
-
return {};
|
|
904
|
-
}
|
|
905
|
-
throw err;
|
|
1081
|
+
catch (err) {
|
|
1082
|
+
if ((0, instance_detail_helper_1.isNotAuthorized)(err) || (0, instance_detail_helper_1.isNotSupportedPipelineStage)(err)) {
|
|
1083
|
+
return {};
|
|
906
1084
|
}
|
|
1085
|
+
throw err;
|
|
907
1086
|
}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1087
|
+
}
|
|
1088
|
+
async _indexSizes(ns) {
|
|
1089
|
+
try {
|
|
1090
|
+
const coll = this._collection(ns, 'CRUD');
|
|
1091
|
+
const aggResult = (await coll
|
|
1092
|
+
.aggregate([
|
|
1093
|
+
{ $collStats: { storageStats: {} } },
|
|
913
1094
|
{
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
ns,
|
|
917
|
-
progress: { $type: 'object' },
|
|
918
|
-
'command.createIndexes': { $exists: true },
|
|
1095
|
+
$project: {
|
|
1096
|
+
indexSizes: { $objectToArray: '$storageStats.indexSizes' },
|
|
919
1097
|
},
|
|
920
1098
|
},
|
|
1099
|
+
{ $unwind: '$indexSizes' },
|
|
921
1100
|
{
|
|
922
|
-
// explode the "indexes" array for each createIndexes command
|
|
923
|
-
$unwind: '$command.indexes',
|
|
924
|
-
},
|
|
925
|
-
{
|
|
926
|
-
// group on index name
|
|
927
1101
|
$group: {
|
|
928
|
-
_id: '$
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1102
|
+
_id: '$indexSizes.k',
|
|
1103
|
+
size: { $sum: { $toDouble: '$indexSizes.v' } },
|
|
1104
|
+
},
|
|
1105
|
+
},
|
|
1106
|
+
])
|
|
1107
|
+
.toArray());
|
|
1108
|
+
return Object.fromEntries(aggResult.map(({ _id, size }) => [_id, size]));
|
|
1109
|
+
}
|
|
1110
|
+
catch (err) {
|
|
1111
|
+
if ((0, instance_detail_helper_1.isNotAuthorized)(err) || (0, instance_detail_helper_1.isNotSupportedPipelineStage)(err)) {
|
|
1112
|
+
return {};
|
|
1113
|
+
}
|
|
1114
|
+
throw err;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
async _indexProgress(ns) {
|
|
1118
|
+
const currentOp = { $currentOp: { allUsers: true, localOps: false } };
|
|
1119
|
+
const pipeline = [
|
|
1120
|
+
// get all ops
|
|
1121
|
+
currentOp,
|
|
1122
|
+
{
|
|
1123
|
+
// filter for createIndexes commands
|
|
1124
|
+
$match: {
|
|
1125
|
+
ns,
|
|
1126
|
+
progress: { $type: 'object' },
|
|
1127
|
+
'command.createIndexes': { $exists: true },
|
|
1128
|
+
},
|
|
1129
|
+
},
|
|
1130
|
+
{
|
|
1131
|
+
// explode the "indexes" array for each createIndexes command
|
|
1132
|
+
$unwind: '$command.indexes',
|
|
1133
|
+
},
|
|
1134
|
+
{
|
|
1135
|
+
// group on index name
|
|
1136
|
+
$group: {
|
|
1137
|
+
_id: '$command.indexes.name',
|
|
1138
|
+
progress: {
|
|
1139
|
+
$first: {
|
|
1140
|
+
$cond: {
|
|
1141
|
+
if: { $gt: ['$progress.total', 0] },
|
|
1142
|
+
then: { $divide: ['$progress.done', '$progress.total'] },
|
|
1143
|
+
else: 0,
|
|
936
1144
|
},
|
|
937
1145
|
},
|
|
938
1146
|
},
|
|
939
1147
|
},
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1148
|
+
},
|
|
1149
|
+
];
|
|
1150
|
+
let currentOps = [];
|
|
1151
|
+
const db = this._database('admin', 'META');
|
|
1152
|
+
try {
|
|
1153
|
+
currentOps = (await db
|
|
1154
|
+
.aggregate(pipeline)
|
|
1155
|
+
.toArray());
|
|
1156
|
+
}
|
|
1157
|
+
catch {
|
|
1158
|
+
// Try limiting the permissions needed:
|
|
1159
|
+
currentOp.$currentOp.allUsers = false;
|
|
943
1160
|
try {
|
|
944
1161
|
currentOps = (await db
|
|
945
1162
|
.aggregate(pipeline)
|
|
946
1163
|
.toArray());
|
|
947
1164
|
}
|
|
948
1165
|
catch {
|
|
949
|
-
//
|
|
950
|
-
currentOp.$currentOp.allUsers = false;
|
|
951
|
-
try {
|
|
952
|
-
currentOps = (await db
|
|
953
|
-
.aggregate(pipeline)
|
|
954
|
-
.toArray());
|
|
955
|
-
}
|
|
956
|
-
catch {
|
|
957
|
-
// ignore errors
|
|
958
|
-
}
|
|
1166
|
+
// ignore errors
|
|
959
1167
|
}
|
|
960
|
-
const indexToProgress = Object.create(null);
|
|
961
|
-
for (const { _id, progress } of currentOps) {
|
|
962
|
-
indexToProgress[_id] = progress;
|
|
963
|
-
}
|
|
964
|
-
return indexToProgress;
|
|
965
1168
|
}
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
_id: ns,
|
|
970
|
-
// unsplittable introduced in SPM-3364 to mark unsharded collections
|
|
971
|
-
// that are still being tracked in the catalog
|
|
972
|
-
unsplittable: { $ne: true },
|
|
973
|
-
}, { ...options, projection: { key: 1, _id: 0 } }, { abortSignal: executionOptions?.abortSignal });
|
|
974
|
-
return docs.length ? docs[0].key : null;
|
|
1169
|
+
const indexToProgress = Object.create(null);
|
|
1170
|
+
for (const { _id, progress } of currentOps) {
|
|
1171
|
+
indexToProgress[_id] = progress;
|
|
975
1172
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1173
|
+
return indexToProgress;
|
|
1174
|
+
}
|
|
1175
|
+
async fetchShardKey(ns, options = {}, executionOptions) {
|
|
1176
|
+
const docs = await this.find('config.collections', {
|
|
1177
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1178
|
+
_id: ns,
|
|
1179
|
+
// unsplittable introduced in SPM-3364 to mark unsharded collections
|
|
1180
|
+
// that are still being tracked in the catalog
|
|
1181
|
+
unsplittable: { $ne: true },
|
|
1182
|
+
}, { ...options, projection: { key: 1, _id: 0 } }, { abortSignal: executionOptions?.abortSignal });
|
|
1183
|
+
return docs.length ? docs[0].key : null;
|
|
1184
|
+
}
|
|
1185
|
+
async _fetchShardKeyWithSilentFail(...args) {
|
|
1186
|
+
try {
|
|
1187
|
+
return await this.fetchShardKey(...args);
|
|
989
1188
|
}
|
|
990
|
-
|
|
991
|
-
if
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
const [name, keys] = compactIndexEntry;
|
|
995
|
-
return (0, index_detail_helper_1.createIndexDefinition)(ns, null, {
|
|
996
|
-
name,
|
|
997
|
-
key: Object.fromEntries(keys),
|
|
998
|
-
});
|
|
999
|
-
});
|
|
1189
|
+
catch (err) {
|
|
1190
|
+
// Rethrow if we aborted along the way.
|
|
1191
|
+
if (this.isCancelError(err)) {
|
|
1192
|
+
throw err;
|
|
1000
1193
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
this._indexSizes(ns),
|
|
1005
|
-
this._indexProgress(ns),
|
|
1006
|
-
this._fetchShardKeyWithSilentFail(ns),
|
|
1007
|
-
]);
|
|
1008
|
-
const maxSize = Math.max(...Object.values(indexSizes));
|
|
1009
|
-
return indexes
|
|
1010
|
-
.filter((index) => {
|
|
1011
|
-
return !!index.name;
|
|
1012
|
-
})
|
|
1013
|
-
.map((index) => {
|
|
1014
|
-
const name = index.name;
|
|
1015
|
-
return (0, index_detail_helper_1.createIndexDefinition)(ns, shardKey ?? null, index, indexStats[name], indexSizes[name], maxSize, indexProgress[name]);
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
async instance() {
|
|
1019
|
-
return {
|
|
1020
|
-
...(await (0, instance_detail_helper_2.getInstance)(this._initializedClient('META'), this._connectionOptions.connectionString)),
|
|
1021
|
-
// Need to get the CSFLE flag from the CRUD client, not the META one
|
|
1022
|
-
csfleMode: this.getCSFLEMode(),
|
|
1023
|
-
};
|
|
1024
|
-
}
|
|
1025
|
-
async insertOne(ns, doc, options) {
|
|
1026
|
-
const coll = this._collection(ns, 'CRUD');
|
|
1027
|
-
return await coll.insertOne(doc, options);
|
|
1028
|
-
}
|
|
1029
|
-
async insertMany(ns, docs, options) {
|
|
1030
|
-
const coll = this._collection(ns, 'CRUD');
|
|
1031
|
-
return await coll.insertMany(docs, options);
|
|
1194
|
+
// Return null on error.
|
|
1195
|
+
// This is oftentimes a lack of permissions to run a find on config.collections.
|
|
1196
|
+
return null;
|
|
1032
1197
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
collMod: collectionName,
|
|
1044
|
-
...flags,
|
|
1198
|
+
}
|
|
1199
|
+
async indexes(ns, options) {
|
|
1200
|
+
if (options?.full === false) {
|
|
1201
|
+
const indexes = Object.entries(await this._collection(ns, 'CRUD').indexes({ ...options, full: false }));
|
|
1202
|
+
return indexes.map((compactIndexEntry) => {
|
|
1203
|
+
const [name, keys] = compactIndexEntry;
|
|
1204
|
+
return (0, index_detail_helper_1.createIndexDefinition)(ns, null, {
|
|
1205
|
+
name,
|
|
1206
|
+
key: Object.fromEntries(keys),
|
|
1207
|
+
});
|
|
1045
1208
|
});
|
|
1046
|
-
// Reset the CSFLE-enabled client (if any) to clear any collection
|
|
1047
|
-
// metadata caches that might still be active.
|
|
1048
|
-
await this._resetCRUDClient();
|
|
1049
|
-
return result;
|
|
1050
|
-
}
|
|
1051
|
-
bulkWrite(ns, operations, options) {
|
|
1052
|
-
return this._collection(ns, 'CRUD').bulkWrite(operations, options);
|
|
1053
1209
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1210
|
+
const [indexes, indexStats, indexSizes, indexProgress, shardKey] = await Promise.all([
|
|
1211
|
+
this._collection(ns, 'CRUD').indexes({ ...options, full: true }),
|
|
1212
|
+
this._indexStats(ns),
|
|
1213
|
+
this._indexSizes(ns),
|
|
1214
|
+
this._indexProgress(ns),
|
|
1215
|
+
this._fetchShardKeyWithSilentFail(ns),
|
|
1216
|
+
]);
|
|
1217
|
+
const maxSize = Math.max(...Object.values(indexSizes));
|
|
1218
|
+
return indexes
|
|
1219
|
+
.filter((index) => {
|
|
1220
|
+
return !!index.name;
|
|
1221
|
+
})
|
|
1222
|
+
.map((index) => {
|
|
1223
|
+
const name = index.name;
|
|
1224
|
+
return (0, index_detail_helper_1.createIndexDefinition)(ns, shardKey ?? null, index, indexStats[name], indexSizes[name], maxSize, indexProgress[name]);
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
async instance() {
|
|
1228
|
+
return {
|
|
1229
|
+
...(await (0, instance_detail_helper_2.getInstance)(this._initializedClient('META'), this._connectionOptions.connectionString)),
|
|
1230
|
+
// Need to get the CSFLE flag from the CRUD client, not the META one
|
|
1231
|
+
csfleMode: this.getCSFLEMode(),
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
1234
|
+
async insertOne(ns, doc, options) {
|
|
1235
|
+
const coll = this._collection(ns, 'CRUD');
|
|
1236
|
+
return await coll.insertOne(doc, options);
|
|
1237
|
+
}
|
|
1238
|
+
async insertMany(ns, docs, options) {
|
|
1239
|
+
const coll = this._collection(ns, 'CRUD');
|
|
1240
|
+
return await coll.insertMany(docs, options);
|
|
1241
|
+
}
|
|
1242
|
+
async updateCollection(ns,
|
|
1243
|
+
// Collection name to update that will be passed to the collMod command will
|
|
1244
|
+
// be derived from the provided namespace, this is why we are explicitly
|
|
1245
|
+
// prohibiting to pass collMod flag here
|
|
1246
|
+
flags = {}) {
|
|
1247
|
+
const collectionName = this._collectionName(ns);
|
|
1248
|
+
const db = this._database(ns, 'CRUD');
|
|
1249
|
+
const result = await (0, run_command_1.runCommand)(db, {
|
|
1250
|
+
// Order of arguments is important here, collMod is a command name and it
|
|
1251
|
+
// should always be the first one in the object
|
|
1252
|
+
collMod: collectionName,
|
|
1253
|
+
...flags,
|
|
1254
|
+
});
|
|
1255
|
+
// Reset the CSFLE-enabled client (if any) to clear any collection
|
|
1256
|
+
// metadata caches that might still be active.
|
|
1257
|
+
await this._resetCRUDClient();
|
|
1258
|
+
return result;
|
|
1259
|
+
}
|
|
1260
|
+
bulkWrite(ns, operations, options) {
|
|
1261
|
+
return this._collection(ns, 'CRUD').bulkWrite(operations, options);
|
|
1262
|
+
}
|
|
1263
|
+
async currentOp() {
|
|
1264
|
+
const db = this._database('admin', 'META');
|
|
1265
|
+
const pipelineWithTruncateOps = [
|
|
1266
|
+
{
|
|
1267
|
+
$currentOp: {
|
|
1268
|
+
allUsers: true,
|
|
1269
|
+
idleConnections: false,
|
|
1270
|
+
truncateOps: false,
|
|
1063
1271
|
},
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1272
|
+
},
|
|
1273
|
+
];
|
|
1274
|
+
const currentOp = await db.aggregate(pipelineWithTruncateOps).toArray();
|
|
1275
|
+
return { inprog: currentOp };
|
|
1276
|
+
}
|
|
1277
|
+
getLastSeenTopology() {
|
|
1278
|
+
return this._lastSeenTopology;
|
|
1279
|
+
}
|
|
1280
|
+
async serverStatus() {
|
|
1281
|
+
const admin = this._database('admin', 'META');
|
|
1282
|
+
return await (0, run_command_1.runCommand)(admin, { serverStatus: 1 }, { enableUtf8Validation: false });
|
|
1283
|
+
}
|
|
1284
|
+
async top() {
|
|
1285
|
+
const adminDb = this._database('admin', 'META');
|
|
1286
|
+
return await (0, run_command_1.runCommand)(adminDb, { top: 1 }, { enableUtf8Validation: false });
|
|
1287
|
+
}
|
|
1288
|
+
async createView(name, sourceNs, pipeline, options = {}) {
|
|
1289
|
+
const createCollectionOptions = {
|
|
1290
|
+
...options,
|
|
1291
|
+
viewOn: this._collectionName(sourceNs),
|
|
1292
|
+
pipeline,
|
|
1293
|
+
};
|
|
1294
|
+
const db = this._database(sourceNs, 'CRUD');
|
|
1295
|
+
return await db.createCollection(name, createCollectionOptions);
|
|
1296
|
+
}
|
|
1297
|
+
_buildSamplingPipeline({ query, size, fields }) {
|
|
1298
|
+
const pipeline = [];
|
|
1299
|
+
if (query && Object.keys(query).length > 0) {
|
|
1300
|
+
pipeline.push({
|
|
1301
|
+
$match: query,
|
|
1302
|
+
});
|
|
1074
1303
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1304
|
+
pipeline.push({
|
|
1305
|
+
$sample: {
|
|
1306
|
+
size: size === 0 ? 0 : size || 1000,
|
|
1307
|
+
},
|
|
1308
|
+
});
|
|
1309
|
+
// add $project stage if projection (fields) was specified
|
|
1310
|
+
if (fields && Object.keys(fields).length > 0) {
|
|
1311
|
+
pipeline.push({
|
|
1312
|
+
$project: fields,
|
|
1313
|
+
});
|
|
1078
1314
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1315
|
+
return pipeline;
|
|
1316
|
+
}
|
|
1317
|
+
sampleCursor(ns, samplingOptions = {}, options = {}, executionOptions) {
|
|
1318
|
+
const pipeline = this._buildSamplingPipeline(samplingOptions);
|
|
1319
|
+
return this.aggregateCursor(ns, pipeline, {
|
|
1320
|
+
allowDiskUse: true,
|
|
1321
|
+
// When the read preference isn't set in the connection string explicitly,
|
|
1322
|
+
// then we allow consumers to default to a read preference, for instance
|
|
1323
|
+
// secondaryPreferred to avoid using the primary for analyzing documents.
|
|
1324
|
+
...this._getOptionsWithFallbackReadPreference(options, executionOptions),
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
sample(ns, samplingOptions = {}, options = {}, executionOptions) {
|
|
1328
|
+
const pipeline = this._buildSamplingPipeline(samplingOptions);
|
|
1329
|
+
return this.aggregate(ns, pipeline, {
|
|
1330
|
+
allowDiskUse: true,
|
|
1331
|
+
// When the read preference isn't set in the connection string explicitly,
|
|
1332
|
+
// then we allow consumers to default to a read preference, for instance
|
|
1333
|
+
// secondaryPreferred to avoid using the primary for analyzing documents.
|
|
1334
|
+
...this._getOptionsWithFallbackReadPreference(options, executionOptions),
|
|
1335
|
+
}, executionOptions);
|
|
1336
|
+
}
|
|
1337
|
+
_startSession(clientType) {
|
|
1338
|
+
const session = this._initializedClient(clientType).startSession();
|
|
1339
|
+
session[kSessionClientType] = clientType;
|
|
1340
|
+
return session;
|
|
1341
|
+
}
|
|
1342
|
+
_killSessions(sessions) {
|
|
1343
|
+
const sessionsArray = Array.isArray(sessions) ? sessions : [sessions];
|
|
1344
|
+
const clientTypes = new Set(sessionsArray.map((s) => s[kSessionClientType]));
|
|
1345
|
+
if (clientTypes.size !== 1) {
|
|
1346
|
+
throw new Error(`Cannot kill sessions without a specific client type: [${[
|
|
1347
|
+
...clientTypes,
|
|
1348
|
+
].join(', ')}]`);
|
|
1349
|
+
}
|
|
1350
|
+
const [clientType] = clientTypes;
|
|
1351
|
+
return (0, run_command_1.runCommand)(this._database('admin', clientType), {
|
|
1352
|
+
killSessions: sessionsArray.map((s) => s.id),
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
isConnected() {
|
|
1356
|
+
// This is better than just returning internal `_isConnecting` as this
|
|
1357
|
+
// actually shows when the client is available on the NativeClient instance
|
|
1358
|
+
// and connected
|
|
1359
|
+
return !!this._metadataClient;
|
|
1360
|
+
}
|
|
1361
|
+
async _cancellableOperation(start, stop = () => Promise.resolve(), abortSignal) {
|
|
1362
|
+
if (!abortSignal) {
|
|
1363
|
+
return await start();
|
|
1364
|
+
}
|
|
1365
|
+
if (abortSignal.aborted) {
|
|
1366
|
+
// AbortSignal.reason is supported from node v17.2.0.
|
|
1367
|
+
throw abortSignal.reason ?? (0, compass_utils_1.createCancelError)();
|
|
1368
|
+
}
|
|
1369
|
+
const session = this._startSession('CRUD');
|
|
1370
|
+
let result;
|
|
1371
|
+
const abort = async () => {
|
|
1372
|
+
const logAbortError = (error) => {
|
|
1373
|
+
this._logger.warn((0, logger_1.mongoLogId)(1_001_000_140), 'Attempting to kill the operation failed', { error: error.message });
|
|
1084
1374
|
};
|
|
1085
|
-
|
|
1086
|
-
|
|
1375
|
+
await stop(session).catch(logAbortError);
|
|
1376
|
+
await this._killSessions(session).catch(logAbortError);
|
|
1377
|
+
};
|
|
1378
|
+
try {
|
|
1379
|
+
result = await (0, compass_utils_1.raceWithAbort)(start(session), abortSignal);
|
|
1087
1380
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
pipeline.push({
|
|
1092
|
-
$match: query,
|
|
1093
|
-
});
|
|
1381
|
+
catch (err) {
|
|
1382
|
+
if ((0, compass_utils_1.isCancelError)(err)) {
|
|
1383
|
+
await abort();
|
|
1094
1384
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1385
|
+
throw err;
|
|
1386
|
+
}
|
|
1387
|
+
return result;
|
|
1388
|
+
}
|
|
1389
|
+
isCancelError(error) {
|
|
1390
|
+
return (0, compass_utils_1.isCancelError)(error);
|
|
1391
|
+
}
|
|
1392
|
+
_setupListeners(client) {
|
|
1393
|
+
if (client) {
|
|
1394
|
+
client.on('connectionCreated', (evt) => {
|
|
1395
|
+
const { address, connectionId } = evt;
|
|
1396
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_027), 'Driver connection created', {
|
|
1397
|
+
address,
|
|
1398
|
+
serverConnectionId: connectionId,
|
|
1399
|
+
});
|
|
1099
1400
|
});
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1401
|
+
client.on('serverDescriptionChanged', (evt) => {
|
|
1402
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_018), 'Server description changed', {
|
|
1403
|
+
address: evt.address,
|
|
1404
|
+
error: evt.newDescription.error?.message ?? null,
|
|
1405
|
+
previousType: evt.previousDescription.type,
|
|
1406
|
+
newType: evt.newDescription.type,
|
|
1104
1407
|
});
|
|
1105
|
-
}
|
|
1106
|
-
return pipeline;
|
|
1107
|
-
}
|
|
1108
|
-
sampleCursor(ns, samplingOptions = {}, options = {}, executionOptions) {
|
|
1109
|
-
const pipeline = this._buildSamplingPipeline(samplingOptions);
|
|
1110
|
-
return this.aggregateCursor(ns, pipeline, {
|
|
1111
|
-
allowDiskUse: true,
|
|
1112
|
-
// When the read preference isn't set in the connection string explicitly,
|
|
1113
|
-
// then we allow consumers to default to a read preference, for instance
|
|
1114
|
-
// secondaryPreferred to avoid using the primary for analyzing documents.
|
|
1115
|
-
...this._getOptionsWithFallbackReadPreference(options, executionOptions),
|
|
1116
1408
|
});
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
allowDiskUse: true,
|
|
1122
|
-
// When the read preference isn't set in the connection string explicitly,
|
|
1123
|
-
// then we allow consumers to default to a read preference, for instance
|
|
1124
|
-
// secondaryPreferred to avoid using the primary for analyzing documents.
|
|
1125
|
-
...this._getOptionsWithFallbackReadPreference(options, executionOptions),
|
|
1126
|
-
}, executionOptions);
|
|
1127
|
-
}
|
|
1128
|
-
_startSession(clientType) {
|
|
1129
|
-
const session = this._initializedClient(clientType).startSession();
|
|
1130
|
-
session[kSessionClientType] = clientType;
|
|
1131
|
-
return session;
|
|
1132
|
-
}
|
|
1133
|
-
_killSessions(sessions) {
|
|
1134
|
-
const sessionsArray = Array.isArray(sessions) ? sessions : [sessions];
|
|
1135
|
-
const clientTypes = new Set(sessionsArray.map((s) => s[kSessionClientType]));
|
|
1136
|
-
if (clientTypes.size !== 1) {
|
|
1137
|
-
throw new Error(`Cannot kill sessions without a specific client type: [${[
|
|
1138
|
-
...clientTypes,
|
|
1139
|
-
].join(', ')}]`);
|
|
1140
|
-
}
|
|
1141
|
-
const [clientType] = clientTypes;
|
|
1142
|
-
return (0, run_command_1.runCommand)(this._database('admin', clientType), {
|
|
1143
|
-
killSessions: sessionsArray.map((s) => s.id),
|
|
1409
|
+
client.on('serverOpening', (evt) => {
|
|
1410
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_019), 'Server opening', {
|
|
1411
|
+
address: evt.address,
|
|
1412
|
+
});
|
|
1144
1413
|
});
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
let result;
|
|
1162
|
-
const abort = async () => {
|
|
1163
|
-
const logAbortError = (error) => {
|
|
1164
|
-
this._logger.warn((0, logger_1.mongoLogId)(1_001_000_140), 'Attempting to kill the operation failed', { error: error.message });
|
|
1414
|
+
client.on('close', () => {
|
|
1415
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_315), 'Client is closed');
|
|
1416
|
+
this._emitter.emit('close');
|
|
1417
|
+
});
|
|
1418
|
+
client.on('serverClosed', (evt) => {
|
|
1419
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_020), 'Server closed', {
|
|
1420
|
+
address: evt.address,
|
|
1421
|
+
});
|
|
1422
|
+
});
|
|
1423
|
+
client.on('topologyDescriptionChanged', (evt) => {
|
|
1424
|
+
this._isWritable = this._checkIsWritable(evt);
|
|
1425
|
+
const attr = {
|
|
1426
|
+
isWritable: this.isWritable(),
|
|
1427
|
+
isMongos: this.isMongos(),
|
|
1428
|
+
previousType: evt.previousDescription.type,
|
|
1429
|
+
newType: evt.newDescription.type,
|
|
1165
1430
|
};
|
|
1166
|
-
|
|
1167
|
-
|
|
1431
|
+
this._logger.info((0, logger_1.mongoLogId)(1_001_000_021), 'Topology description changed', attr);
|
|
1432
|
+
this._lastSeenTopology = evt.newDescription;
|
|
1433
|
+
this._emitter.emit('topologyDescriptionChanged', evt);
|
|
1434
|
+
});
|
|
1435
|
+
// Heartbeat events are fairly noisy. We put some effort into
|
|
1436
|
+
// making sure that we only log events that actually contain
|
|
1437
|
+
// meaningful information.
|
|
1438
|
+
const heartbeatStatusMap = new Map();
|
|
1439
|
+
const isSignificantDurationChange = (before, after) => {
|
|
1440
|
+
// Changes in pings below 200ms are not particularly concerning here.
|
|
1441
|
+
before = Math.max(before, 200);
|
|
1442
|
+
after = Math.max(after, 200);
|
|
1443
|
+
// Check if changes is at least 2× (in either direction).
|
|
1444
|
+
return Math.abs(Math.log2(before / after)) >= 1;
|
|
1168
1445
|
};
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1178
|
-
return result;
|
|
1179
|
-
}
|
|
1180
|
-
isCancelError(error) {
|
|
1181
|
-
return (0, compass_utils_1.isCancelError)(error);
|
|
1182
|
-
}
|
|
1183
|
-
_setupListeners(client) {
|
|
1184
|
-
if (client) {
|
|
1185
|
-
client.on('connectionCreated', (evt) => {
|
|
1186
|
-
const { address, connectionId } = evt;
|
|
1187
|
-
this._logger.info((0, logger_1.mongoLogId)(1_001_000_027), 'Driver connection created', {
|
|
1188
|
-
address,
|
|
1189
|
-
serverConnectionId: connectionId,
|
|
1190
|
-
});
|
|
1191
|
-
});
|
|
1192
|
-
client.on('serverDescriptionChanged', (evt) => {
|
|
1193
|
-
this._logger.info((0, logger_1.mongoLogId)(1_001_000_018), 'Server description changed', {
|
|
1194
|
-
address: evt.address,
|
|
1195
|
-
error: evt.newDescription.error?.message ?? null,
|
|
1196
|
-
previousType: evt.previousDescription.type,
|
|
1197
|
-
newType: evt.newDescription.type,
|
|
1446
|
+
client.on('serverHeartbeatSucceeded', (evt) => {
|
|
1447
|
+
const previousStatus = heartbeatStatusMap.get(evt.connectionId);
|
|
1448
|
+
if (!previousStatus ||
|
|
1449
|
+
previousStatus.failure ||
|
|
1450
|
+
isSignificantDurationChange(previousStatus.duration, evt.duration)) {
|
|
1451
|
+
heartbeatStatusMap.set(evt.connectionId, {
|
|
1452
|
+
failure: null,
|
|
1453
|
+
duration: evt.duration,
|
|
1198
1454
|
});
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
address: evt.address,
|
|
1455
|
+
this._logger.debug((0, logger_1.mongoLogId)(1_001_000_022), 'Server heartbeat succeeded', {
|
|
1456
|
+
connectionId: evt.connectionId,
|
|
1457
|
+
duration: evt.duration,
|
|
1203
1458
|
});
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1461
|
+
client.on('serverHeartbeatFailed', (evt) => {
|
|
1462
|
+
const previousStatus = heartbeatStatusMap.get(evt.connectionId);
|
|
1463
|
+
if (!previousStatus ||
|
|
1464
|
+
!previousStatus.failure ||
|
|
1465
|
+
isSignificantDurationChange(previousStatus.duration, evt.duration)) {
|
|
1466
|
+
heartbeatStatusMap.set(evt.connectionId, {
|
|
1467
|
+
failure: evt.failure.message,
|
|
1468
|
+
duration: evt.duration,
|
|
1212
1469
|
});
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
isWritable: this.isWritable(),
|
|
1218
|
-
isMongos: this.isMongos(),
|
|
1219
|
-
previousType: evt.previousDescription.type,
|
|
1220
|
-
newType: evt.newDescription.type,
|
|
1221
|
-
};
|
|
1222
|
-
this._logger.info((0, logger_1.mongoLogId)(1_001_000_021), 'Topology description changed', attr);
|
|
1223
|
-
this._lastSeenTopology = evt.newDescription;
|
|
1224
|
-
this._emitter.emit('topologyDescriptionChanged', evt);
|
|
1225
|
-
});
|
|
1226
|
-
// Heartbeat events are fairly noisy. We put some effort into
|
|
1227
|
-
// making sure that we only log events that actually contain
|
|
1228
|
-
// meaningful information.
|
|
1229
|
-
const heartbeatStatusMap = new Map();
|
|
1230
|
-
const isSignificantDurationChange = (before, after) => {
|
|
1231
|
-
// Changes in pings below 200ms are not particularly concerning here.
|
|
1232
|
-
before = Math.max(before, 200);
|
|
1233
|
-
after = Math.max(after, 200);
|
|
1234
|
-
// Check if changes is at least 2× (in either direction).
|
|
1235
|
-
return Math.abs(Math.log2(before / after)) >= 1;
|
|
1236
|
-
};
|
|
1237
|
-
client.on('serverHeartbeatSucceeded', (evt) => {
|
|
1238
|
-
const previousStatus = heartbeatStatusMap.get(evt.connectionId);
|
|
1239
|
-
if (!previousStatus ||
|
|
1240
|
-
previousStatus.failure ||
|
|
1241
|
-
isSignificantDurationChange(previousStatus.duration, evt.duration)) {
|
|
1242
|
-
heartbeatStatusMap.set(evt.connectionId, {
|
|
1243
|
-
failure: null,
|
|
1244
|
-
duration: evt.duration,
|
|
1245
|
-
});
|
|
1246
|
-
this._logger.debug((0, logger_1.mongoLogId)(1_001_000_022), 'Server heartbeat succeeded', {
|
|
1247
|
-
connectionId: evt.connectionId,
|
|
1248
|
-
duration: evt.duration,
|
|
1249
|
-
});
|
|
1250
|
-
}
|
|
1251
|
-
});
|
|
1252
|
-
client.on('serverHeartbeatFailed', (evt) => {
|
|
1253
|
-
const previousStatus = heartbeatStatusMap.get(evt.connectionId);
|
|
1254
|
-
if (!previousStatus ||
|
|
1255
|
-
!previousStatus.failure ||
|
|
1256
|
-
isSignificantDurationChange(previousStatus.duration, evt.duration)) {
|
|
1257
|
-
heartbeatStatusMap.set(evt.connectionId, {
|
|
1258
|
-
failure: evt.failure.message,
|
|
1259
|
-
duration: evt.duration,
|
|
1260
|
-
});
|
|
1261
|
-
this._logger.warn((0, logger_1.mongoLogId)(1_001_000_023), 'Server heartbeat failed', {
|
|
1262
|
-
connectionId: evt.connectionId,
|
|
1263
|
-
duration: evt.duration,
|
|
1264
|
-
failure: evt.failure.message,
|
|
1265
|
-
});
|
|
1266
|
-
}
|
|
1267
|
-
this._emitter.emit('serverHeartbeatFailed', evt);
|
|
1268
|
-
});
|
|
1269
|
-
client.on('commandStarted', (evt) => {
|
|
1270
|
-
const { address, connectionId, requestId, commandName, databaseName } = evt;
|
|
1271
|
-
this._logger.debug((0, logger_1.mongoLogId)(1_001_000_028), 'Driver command started', {
|
|
1272
|
-
address,
|
|
1273
|
-
databaseName,
|
|
1274
|
-
serverConnectionId: connectionId,
|
|
1275
|
-
requestId,
|
|
1276
|
-
commandName,
|
|
1470
|
+
this._logger.warn((0, logger_1.mongoLogId)(1_001_000_023), 'Server heartbeat failed', {
|
|
1471
|
+
connectionId: evt.connectionId,
|
|
1472
|
+
duration: evt.duration,
|
|
1473
|
+
failure: evt.failure.message,
|
|
1277
1474
|
});
|
|
1475
|
+
}
|
|
1476
|
+
this._emitter.emit('serverHeartbeatFailed', evt);
|
|
1477
|
+
});
|
|
1478
|
+
client.on('commandStarted', (evt) => {
|
|
1479
|
+
const { address, connectionId, requestId, commandName, databaseName } = evt;
|
|
1480
|
+
this._logger.debug((0, logger_1.mongoLogId)(1_001_000_028), 'Driver command started', {
|
|
1481
|
+
address,
|
|
1482
|
+
databaseName,
|
|
1483
|
+
serverConnectionId: connectionId,
|
|
1484
|
+
requestId,
|
|
1485
|
+
commandName,
|
|
1278
1486
|
});
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1487
|
+
});
|
|
1488
|
+
client.on('commandSucceeded', (evt) => {
|
|
1489
|
+
const { address, connectionId, duration, requestId, commandName } = evt;
|
|
1490
|
+
this._logger.debug((0, logger_1.mongoLogId)(1_001_000_029), 'Driver command succeeded', {
|
|
1491
|
+
address,
|
|
1492
|
+
requestId,
|
|
1493
|
+
serverConnectionId: connectionId,
|
|
1494
|
+
duration,
|
|
1495
|
+
commandName,
|
|
1288
1496
|
});
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1497
|
+
});
|
|
1498
|
+
client.on('commandFailed', (evt) => {
|
|
1499
|
+
const { address, connectionId, duration, requestId, commandName, failure, } = evt;
|
|
1500
|
+
this._logger.debug((0, logger_1.mongoLogId)(1_001_000_030), 'Driver command failed', {
|
|
1501
|
+
address,
|
|
1502
|
+
serverConnectionId: connectionId,
|
|
1503
|
+
duration,
|
|
1504
|
+
requestId,
|
|
1505
|
+
commandName,
|
|
1506
|
+
failure: failure.message,
|
|
1299
1507
|
});
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
_initializedClient(type) {
|
|
1303
|
-
if (type !== 'CRUD' && type !== 'META') {
|
|
1304
|
-
throw new Error(`Invalid client type: ${type}`);
|
|
1305
|
-
}
|
|
1306
|
-
const client = type === 'CRUD' && this._useCRUDClient
|
|
1307
|
-
? this._crudClient
|
|
1308
|
-
: this._metadataClient;
|
|
1309
|
-
if (!client) {
|
|
1310
|
-
throw new Error(`Client not yet initialized [${type}]`);
|
|
1311
|
-
}
|
|
1312
|
-
return client;
|
|
1313
|
-
}
|
|
1314
|
-
_getCSFLECollectionTracker() {
|
|
1315
|
-
if (!this._csfleCollectionTracker) {
|
|
1316
|
-
throw new Error(`Client not yet initialized [CSFLECollectionTracker]`);
|
|
1317
|
-
}
|
|
1318
|
-
return this._csfleCollectionTracker;
|
|
1508
|
+
});
|
|
1319
1509
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1510
|
+
}
|
|
1511
|
+
_initializedClient(type) {
|
|
1512
|
+
if (type !== 'CRUD' && type !== 'META') {
|
|
1513
|
+
throw new Error(`Invalid client type: ${type}`);
|
|
1322
1514
|
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1515
|
+
const client = type === 'CRUD' && this._useCRUDClient
|
|
1516
|
+
? this._crudClient
|
|
1517
|
+
: this._metadataClient;
|
|
1518
|
+
if (!client) {
|
|
1519
|
+
throw new Error(`Client not yet initialized [${type}]`);
|
|
1325
1520
|
}
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
});
|
|
1332
|
-
const normalized = (0, instance_detail_helper_2.adaptDatabaseInfo)(stats);
|
|
1333
|
-
return { name, ...normalized };
|
|
1521
|
+
return client;
|
|
1522
|
+
}
|
|
1523
|
+
_getCSFLECollectionTracker() {
|
|
1524
|
+
if (!this._csfleCollectionTracker) {
|
|
1525
|
+
throw new Error(`Client not yet initialized [CSFLECollectionTracker]`);
|
|
1334
1526
|
}
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
}, {
|
|
1527
|
+
return this._csfleCollectionTracker;
|
|
1528
|
+
}
|
|
1529
|
+
isUpdateAllowed(ns, originalDocument) {
|
|
1530
|
+
return this._getCSFLECollectionTracker().isUpdateAllowed(ns, originalDocument);
|
|
1531
|
+
}
|
|
1532
|
+
knownSchemaForCollection(ns) {
|
|
1533
|
+
return this._getCSFLECollectionTracker().knownSchemaForCollection(ns);
|
|
1534
|
+
}
|
|
1535
|
+
async databaseStats(name) {
|
|
1536
|
+
const db = this._database(name, 'META');
|
|
1537
|
+
const stats = await (0, run_command_1.runCommand)(db, { dbStats: 1 }, {
|
|
1538
|
+
enableUtf8Validation: false,
|
|
1539
|
+
...maybeOverrideReadPreference(this.isMongos(), this._crudClient?.readPreference),
|
|
1540
|
+
});
|
|
1541
|
+
const normalized = (0, instance_detail_helper_2.adaptDatabaseInfo)(stats);
|
|
1542
|
+
return { name, ...normalized };
|
|
1543
|
+
}
|
|
1544
|
+
async previewUpdate(ns, filter, update, executionOptions = {}) {
|
|
1545
|
+
const { abortSignal = new AbortController().signal, sample = 10, timeout = 1000, } = executionOptions;
|
|
1546
|
+
const startTimeMS = Date.now();
|
|
1547
|
+
const remainingTimeoutMS = () => Math.max(1, timeout - (Date.now() - startTimeMS));
|
|
1548
|
+
return await this._cancellableOperation(async (session) => {
|
|
1549
|
+
if (!session) {
|
|
1550
|
+
throw new Error('Could not open session.');
|
|
1551
|
+
}
|
|
1552
|
+
try {
|
|
1553
|
+
return await session.withTransaction(async () => {
|
|
1554
|
+
const coll = this._collection(ns, 'CRUD');
|
|
1555
|
+
const docsToPreview = await coll
|
|
1556
|
+
.find(filter, {
|
|
1557
|
+
session,
|
|
1558
|
+
maxTimeMS: remainingTimeoutMS(),
|
|
1559
|
+
// by using promoteValues: false we can spot BSON type changes
|
|
1560
|
+
// when diffing. ie. new Double(1) -> new Int32(1)
|
|
1561
|
+
promoteValues: false,
|
|
1562
|
+
})
|
|
1563
|
+
.sort({ _id: 1 })
|
|
1564
|
+
.limit(sample)
|
|
1565
|
+
.toArray();
|
|
1566
|
+
const idsToPreview = docsToPreview.map((doc) => doc._id);
|
|
1567
|
+
await coll.updateMany({ _id: { $in: idsToPreview } }, update, {
|
|
1568
|
+
session,
|
|
1378
1569
|
maxTimeMS: remainingTimeoutMS(),
|
|
1379
1570
|
});
|
|
1571
|
+
const changedDocs = await coll
|
|
1572
|
+
.find({ _id: { $in: idsToPreview } }, {
|
|
1573
|
+
session,
|
|
1574
|
+
maxTimeMS: remainingTimeoutMS(),
|
|
1575
|
+
promoteValues: false,
|
|
1576
|
+
})
|
|
1577
|
+
.sort({ _id: 1 })
|
|
1578
|
+
.toArray();
|
|
1579
|
+
await session.abortTransaction();
|
|
1580
|
+
await session.endSession();
|
|
1581
|
+
const changes = docsToPreview.map((before, idx) => ({
|
|
1582
|
+
before,
|
|
1583
|
+
after: changedDocs[idx],
|
|
1584
|
+
}));
|
|
1585
|
+
return { changes };
|
|
1586
|
+
}, {
|
|
1587
|
+
maxTimeMS: remainingTimeoutMS(),
|
|
1588
|
+
});
|
|
1589
|
+
}
|
|
1590
|
+
catch (err) {
|
|
1591
|
+
if (isTransactionAbortError(err)) {
|
|
1592
|
+
// The transaction was aborted while it was still calculating the
|
|
1593
|
+
// preview. Just return something here rather than erroring. No
|
|
1594
|
+
// reason to abort the transaction or end the session again because
|
|
1595
|
+
// we only got here because that already happened.
|
|
1596
|
+
return { changes: [] };
|
|
1380
1597
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
// we only got here because that already happened.
|
|
1387
|
-
return { changes: [] };
|
|
1388
|
-
}
|
|
1389
|
-
// The only way this if statement would be true is if aborting the
|
|
1390
|
-
// transaction and ending the session itself failed above. Unlikely.
|
|
1391
|
-
if (session.inTransaction()) {
|
|
1392
|
-
await session.abortTransaction();
|
|
1393
|
-
await session.endSession();
|
|
1394
|
-
}
|
|
1395
|
-
throw err;
|
|
1598
|
+
// The only way this if statement would be true is if aborting the
|
|
1599
|
+
// transaction and ending the session itself failed above. Unlikely.
|
|
1600
|
+
if (session.inTransaction()) {
|
|
1601
|
+
await session.abortTransaction();
|
|
1602
|
+
await session.endSession();
|
|
1396
1603
|
}
|
|
1397
|
-
|
|
1398
|
-
// Rely on the session being killed when we cancel the operation. It can
|
|
1399
|
-
// take a few seconds before the driver reacts, but the Promise.race()
|
|
1400
|
-
// against the abort signal should cause the UI to immediately be
|
|
1401
|
-
// notified that the operation was cancelled. We don't abort the
|
|
1402
|
-
// transaction or end the session as well because the code we run inside
|
|
1403
|
-
// session.withTransaction() above would experience race conditions.
|
|
1404
|
-
}, abortSignal);
|
|
1405
|
-
}
|
|
1406
|
-
/**
|
|
1407
|
-
* @param databaseName - The name of the database.
|
|
1408
|
-
* @param collectionName - The name of the collection.
|
|
1409
|
-
* @param data - The result of the collStats command.
|
|
1410
|
-
*/
|
|
1411
|
-
_buildCollectionStats(databaseName, collectionName, data) {
|
|
1412
|
-
return {
|
|
1413
|
-
ns: databaseName + '.' + collectionName,
|
|
1414
|
-
name: collectionName,
|
|
1415
|
-
database: databaseName,
|
|
1416
|
-
is_capped: data.capped,
|
|
1417
|
-
document_count: data.count ?? 0,
|
|
1418
|
-
document_size: data.size,
|
|
1419
|
-
avg_document_size: data.avgObjSize ?? 0,
|
|
1420
|
-
storage_size: data.storageSize ?? 0,
|
|
1421
|
-
free_storage_size: data.freeStorageSize ?? 0,
|
|
1422
|
-
index_count: data.nindexes ?? 0,
|
|
1423
|
-
index_size: data.totalIndexSize ?? 0,
|
|
1424
|
-
bucket_count: data.bucket_count,
|
|
1425
|
-
avg_bucket_size: data.avg_bucket_size,
|
|
1426
|
-
};
|
|
1427
|
-
}
|
|
1428
|
-
/**
|
|
1429
|
-
* Get the collection to operate on.
|
|
1430
|
-
*
|
|
1431
|
-
* @param ns - The namespace.
|
|
1432
|
-
*/
|
|
1433
|
-
_collection(ns, type) {
|
|
1434
|
-
return this._initializedClient(type)
|
|
1435
|
-
.db(this._databaseName(ns))
|
|
1436
|
-
.collection(this._collectionName(ns));
|
|
1437
|
-
}
|
|
1438
|
-
/**
|
|
1439
|
-
* Get the database to operate on.
|
|
1440
|
-
*
|
|
1441
|
-
* @param ns - The namespace.
|
|
1442
|
-
*/
|
|
1443
|
-
_database(ns, type) {
|
|
1444
|
-
return this._initializedClient(type).db(this._databaseName(ns));
|
|
1445
|
-
}
|
|
1446
|
-
/**
|
|
1447
|
-
* Get the collection name from a namespace.
|
|
1448
|
-
*
|
|
1449
|
-
* @param ns - The namespace in database.collection format.
|
|
1450
|
-
*/
|
|
1451
|
-
_collectionName(ns) {
|
|
1452
|
-
return (0, mongodb_ns_1.default)(ns).collection;
|
|
1453
|
-
}
|
|
1454
|
-
/**
|
|
1455
|
-
* Get the database name from a namespace.
|
|
1456
|
-
*
|
|
1457
|
-
* @param ns - The namespace in database.collection format.
|
|
1458
|
-
*/
|
|
1459
|
-
_databaseName(ns) {
|
|
1460
|
-
return (0, mongodb_ns_1.default)(ns).database;
|
|
1461
|
-
}
|
|
1462
|
-
/**
|
|
1463
|
-
* Determine if the hello response indicates a writable server.
|
|
1464
|
-
*
|
|
1465
|
-
* @param evt - The topology description changed event.
|
|
1466
|
-
*
|
|
1467
|
-
* @returns If the server is writable.
|
|
1468
|
-
*/
|
|
1469
|
-
_checkIsWritable(evt) {
|
|
1470
|
-
return [...evt.newDescription.servers.values()].some((server) => server.isWritable);
|
|
1471
|
-
}
|
|
1472
|
-
_cleanup() {
|
|
1473
|
-
this._emitter.removeAllListeners();
|
|
1474
|
-
this._metadataClient?.removeAllListeners?.();
|
|
1475
|
-
this._crudClient?.removeAllListeners?.();
|
|
1476
|
-
this._metadataClient = undefined;
|
|
1477
|
-
this._crudClient = undefined;
|
|
1478
|
-
this._tunnel = undefined;
|
|
1479
|
-
this._state = undefined;
|
|
1480
|
-
this._mongoClientConnectionOptions = undefined;
|
|
1481
|
-
this._isWritable = false;
|
|
1482
|
-
this._isConnecting = false;
|
|
1483
|
-
}
|
|
1484
|
-
async _resetCRUDClient() {
|
|
1485
|
-
if (this.getCSFLEMode() === 'unavailable') {
|
|
1486
|
-
// No separate client in use, don't do anything
|
|
1487
|
-
return;
|
|
1488
|
-
}
|
|
1489
|
-
const crudClient = this._crudClient;
|
|
1490
|
-
if (!crudClient) {
|
|
1491
|
-
// In disconnected state, don't do anything
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
const newClient = await crudClient[connect_mongo_client_1.createClonedClient]();
|
|
1495
|
-
if (this._crudClient === crudClient) {
|
|
1496
|
-
this._crudClient = newClient;
|
|
1497
|
-
await crudClient.close();
|
|
1498
|
-
}
|
|
1499
|
-
else {
|
|
1500
|
-
// If _crudClient has changed between start and end of
|
|
1501
|
-
// connection establishment, don't do anything, just
|
|
1502
|
-
// close and discard the new client.
|
|
1503
|
-
await newClient.close();
|
|
1604
|
+
throw err;
|
|
1504
1605
|
}
|
|
1606
|
+
}, async () => {
|
|
1607
|
+
// Rely on the session being killed when we cancel the operation. It can
|
|
1608
|
+
// take a few seconds before the driver reacts, but the Promise.race()
|
|
1609
|
+
// against the abort signal should cause the UI to immediately be
|
|
1610
|
+
// notified that the operation was cancelled. We don't abort the
|
|
1611
|
+
// transaction or end the session as well because the code we run inside
|
|
1612
|
+
// session.withTransaction() above would experience race conditions.
|
|
1613
|
+
}, abortSignal);
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1616
|
+
* @param databaseName - The name of the database.
|
|
1617
|
+
* @param collectionName - The name of the collection.
|
|
1618
|
+
* @param data - The result of the collStats command.
|
|
1619
|
+
*/
|
|
1620
|
+
_buildCollectionStats(databaseName, collectionName, data) {
|
|
1621
|
+
return {
|
|
1622
|
+
ns: databaseName + '.' + collectionName,
|
|
1623
|
+
name: collectionName,
|
|
1624
|
+
database: databaseName,
|
|
1625
|
+
is_capped: data.capped,
|
|
1626
|
+
document_count: data.count ?? 0,
|
|
1627
|
+
document_size: data.size,
|
|
1628
|
+
avg_document_size: data.avgObjSize ?? 0,
|
|
1629
|
+
storage_size: data.storageSize ?? 0,
|
|
1630
|
+
free_storage_size: data.freeStorageSize ?? 0,
|
|
1631
|
+
index_count: data.nindexes ?? 0,
|
|
1632
|
+
index_size: data.totalIndexSize ?? 0,
|
|
1633
|
+
bucket_count: data.bucket_count,
|
|
1634
|
+
avg_bucket_size: data.avg_bucket_size,
|
|
1635
|
+
};
|
|
1636
|
+
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Get the collection to operate on.
|
|
1639
|
+
*
|
|
1640
|
+
* @param ns - The namespace.
|
|
1641
|
+
*/
|
|
1642
|
+
_collection(ns, type) {
|
|
1643
|
+
return this._initializedClient(type)
|
|
1644
|
+
.db(this._databaseName(ns))
|
|
1645
|
+
.collection(this._collectionName(ns));
|
|
1646
|
+
}
|
|
1647
|
+
/**
|
|
1648
|
+
* Get the database to operate on.
|
|
1649
|
+
*
|
|
1650
|
+
* @param ns - The namespace.
|
|
1651
|
+
*/
|
|
1652
|
+
_database(ns, type) {
|
|
1653
|
+
return this._initializedClient(type).db(this._databaseName(ns));
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Get the collection name from a namespace.
|
|
1657
|
+
*
|
|
1658
|
+
* @param ns - The namespace in database.collection format.
|
|
1659
|
+
*/
|
|
1660
|
+
_collectionName(ns) {
|
|
1661
|
+
return (0, mongodb_ns_1.default)(ns).collection;
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* Get the database name from a namespace.
|
|
1665
|
+
*
|
|
1666
|
+
* @param ns - The namespace in database.collection format.
|
|
1667
|
+
*/
|
|
1668
|
+
_databaseName(ns) {
|
|
1669
|
+
return (0, mongodb_ns_1.default)(ns).database;
|
|
1670
|
+
}
|
|
1671
|
+
/**
|
|
1672
|
+
* Determine if the hello response indicates a writable server.
|
|
1673
|
+
*
|
|
1674
|
+
* @param evt - The topology description changed event.
|
|
1675
|
+
*
|
|
1676
|
+
* @returns If the server is writable.
|
|
1677
|
+
*/
|
|
1678
|
+
_checkIsWritable(evt) {
|
|
1679
|
+
return [...evt.newDescription.servers.values()].some((server) => server.isWritable);
|
|
1680
|
+
}
|
|
1681
|
+
_cleanup() {
|
|
1682
|
+
this._emitter.removeAllListeners();
|
|
1683
|
+
this._metadataClient?.removeAllListeners?.();
|
|
1684
|
+
this._crudClient?.removeAllListeners?.();
|
|
1685
|
+
this._metadataClient = undefined;
|
|
1686
|
+
this._crudClient = undefined;
|
|
1687
|
+
this._tunnel = undefined;
|
|
1688
|
+
this._state = undefined;
|
|
1689
|
+
this._mongoClientConnectionOptions = undefined;
|
|
1690
|
+
this._isWritable = false;
|
|
1691
|
+
this._isConnecting = false;
|
|
1692
|
+
}
|
|
1693
|
+
async _resetCRUDClient() {
|
|
1694
|
+
if (this.getCSFLEMode() === 'unavailable') {
|
|
1695
|
+
// No separate client in use, don't do anything
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
const crudClient = this._crudClient;
|
|
1699
|
+
if (!crudClient) {
|
|
1700
|
+
// In disconnected state, don't do anything
|
|
1701
|
+
return;
|
|
1702
|
+
}
|
|
1703
|
+
const newClient = await crudClient[connect_mongo_client_1.createClonedClient]();
|
|
1704
|
+
if (this._crudClient === crudClient) {
|
|
1705
|
+
this._crudClient = newClient;
|
|
1706
|
+
await crudClient.close();
|
|
1707
|
+
}
|
|
1708
|
+
else {
|
|
1709
|
+
// If _crudClient has changed between start and end of
|
|
1710
|
+
// connection establishment, don't do anything, just
|
|
1711
|
+
// close and discard the new client.
|
|
1712
|
+
await newClient.close();
|
|
1505
1713
|
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
return
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
}
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
: undefined,
|
|
1543
|
-
});
|
|
1544
|
-
}
|
|
1545
|
-
async getUpdatedSecrets() {
|
|
1546
|
-
if (!this._state)
|
|
1547
|
-
return {};
|
|
1548
|
-
return {
|
|
1549
|
-
oidc: {
|
|
1550
|
-
serializedState: await this._state.oidcPlugin.serialize(),
|
|
1551
|
-
},
|
|
1552
|
-
};
|
|
1553
|
-
}
|
|
1554
|
-
async listStreamProcessors(filter) {
|
|
1555
|
-
const adminDb = this._database('admin', 'CRUD');
|
|
1556
|
-
const { streamProcessors } = await (0, run_command_1.runCommand)(adminDb, {
|
|
1557
|
-
listStreamProcessors: 1,
|
|
1558
|
-
filter,
|
|
1559
|
-
});
|
|
1560
|
-
return streamProcessors;
|
|
1561
|
-
}
|
|
1562
|
-
async startStreamProcessor(name) {
|
|
1563
|
-
const adminDb = this._database('admin', 'CRUD');
|
|
1564
|
-
await (0, run_command_1.runCommand)(adminDb, { startStreamProcessor: name });
|
|
1565
|
-
}
|
|
1566
|
-
async stopStreamProcessor(name) {
|
|
1567
|
-
const adminDb = this._database('admin', 'CRUD');
|
|
1568
|
-
await (0, run_command_1.runCommand)(adminDb, { stopStreamProcessor: name });
|
|
1569
|
-
}
|
|
1570
|
-
async dropStreamProcessor(name) {
|
|
1571
|
-
const adminDb = this._database('admin', 'CRUD');
|
|
1572
|
-
await (0, run_command_1.runCommand)(adminDb, { dropStreamProcessor: name });
|
|
1573
|
-
}
|
|
1574
|
-
},
|
|
1575
|
-
(() => {
|
|
1576
|
-
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
1577
|
-
_collectionStats_decorators = [op((0, logger_1.mongoLogId)(1_001_000_178), ([dbName, collName], result) => {
|
|
1578
|
-
return { ns: `${dbName}.${collName}`, ...(result && { result }) };
|
|
1579
|
-
})];
|
|
1580
|
-
_collectionInfo_decorators = [op((0, logger_1.mongoLogId)(1_001_000_179))];
|
|
1581
|
-
_killOp_decorators = [op((0, logger_1.mongoLogId)(1_001_000_031))];
|
|
1582
|
-
__connectionStatus_decorators = [op((0, logger_1.mongoLogId)(1_001_000_100))];
|
|
1583
|
-
_listCollections_decorators = [op((0, logger_1.mongoLogId)(1_001_000_032), ([databaseName, , options], colls) => {
|
|
1584
|
-
return {
|
|
1585
|
-
db: databaseName,
|
|
1586
|
-
nameOnly: options?.nameOnly ?? false,
|
|
1587
|
-
...(colls && { collectionsCount: colls.length }),
|
|
1588
|
-
};
|
|
1589
|
-
})];
|
|
1590
|
-
_listDatabases_decorators = [op((0, logger_1.mongoLogId)(1_001_000_033), ([options], dbs) => {
|
|
1591
|
-
return {
|
|
1592
|
-
nameOnly: options?.nameOnly ?? false,
|
|
1593
|
-
...(dbs && { databasesCount: dbs.length }),
|
|
1594
|
-
};
|
|
1595
|
-
})];
|
|
1596
|
-
_estimatedCount_decorators = [op((0, logger_1.mongoLogId)(1_001_000_034), ([ns, options]) => {
|
|
1597
|
-
return { ns, maxTimeMS: options?.maxTimeMS };
|
|
1598
|
-
})];
|
|
1599
|
-
_count_decorators = [op((0, logger_1.mongoLogId)(1_001_000_035))];
|
|
1600
|
-
_createCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_036), ([ns, options], result) => {
|
|
1601
|
-
return { ns, options, ...(result && { result }) };
|
|
1602
|
-
})];
|
|
1603
|
-
_createIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_037), ([ns, spec, options], result) => {
|
|
1604
|
-
return { ns, spec, options, ...(result && { result }) };
|
|
1605
|
-
})];
|
|
1606
|
-
_deleteOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_038), ([ns], result) => {
|
|
1607
|
-
return { ns, ...(result && { result }) };
|
|
1608
|
-
})];
|
|
1609
|
-
_deleteMany_decorators = [op((0, logger_1.mongoLogId)(1_001_000_039), ([ns], result) => {
|
|
1610
|
-
return { ns, ...(result && { result }) };
|
|
1611
|
-
})];
|
|
1612
|
-
_dropCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_059), ([ns], result) => {
|
|
1613
|
-
return { ns, ...(result && { result }) };
|
|
1614
|
-
})];
|
|
1615
|
-
_renameCollection_decorators = [op((0, logger_1.mongoLogId)(1_001_000_276))];
|
|
1616
|
-
_dropDatabase_decorators = [op((0, logger_1.mongoLogId)(1_001_000_040), ([db], result) => {
|
|
1617
|
-
return { db, ...(result && { result }) };
|
|
1618
|
-
})];
|
|
1619
|
-
_dropIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_182), ([ns, name], result) => {
|
|
1620
|
-
return { ns, name, ...(result && { result }) };
|
|
1621
|
-
})];
|
|
1622
|
-
_isListSearchIndexesSupported_decorators = [op((0, logger_1.mongoLogId)(1_001_000_237))];
|
|
1623
|
-
_getSearchIndexes_decorators = [op((0, logger_1.mongoLogId)(1_001_000_238))];
|
|
1624
|
-
_createSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_239))];
|
|
1625
|
-
_updateSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_240))];
|
|
1626
|
-
_dropSearchIndex_decorators = [op((0, logger_1.mongoLogId)(1_001_000_241))];
|
|
1627
|
-
_aggregateCursor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_041), ([ns, pipeline, options]) => {
|
|
1628
|
-
return {
|
|
1629
|
-
ns,
|
|
1630
|
-
stages: pipeline.map((stage) => Object.keys(stage)[0]),
|
|
1631
|
-
maxTimeMS: options?.maxTimeMS,
|
|
1632
|
-
};
|
|
1633
|
-
})];
|
|
1634
|
-
_aggregate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_181), ([ns, pipeline, options]) => {
|
|
1635
|
-
return {
|
|
1636
|
-
ns,
|
|
1637
|
-
stages: pipeline.map((stage) => Object.keys(stage)[0]),
|
|
1638
|
-
maxTimeMS: options?.maxTimeMS,
|
|
1639
|
-
};
|
|
1640
|
-
})];
|
|
1641
|
-
_find_decorators = [op((0, logger_1.mongoLogId)(1_001_000_060), ([ns, , options]) => {
|
|
1642
|
-
return { ns, maxTimeMS: options?.maxTimeMS };
|
|
1643
|
-
})];
|
|
1644
|
-
_findCursor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_043))];
|
|
1645
|
-
_findOneAndReplace_decorators = [op((0, logger_1.mongoLogId)(1_001_000_044))];
|
|
1646
|
-
_findOneAndUpdate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_045))];
|
|
1647
|
-
_updateOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_183))];
|
|
1648
|
-
_replaceOne_decorators = [op((0, logger_1.mongoLogId)(1_001_000_191))];
|
|
1649
|
-
_explainFind_decorators = [op((0, logger_1.mongoLogId)(1_001_000_046), ([ns, , , executionOptions]) => {
|
|
1650
|
-
return {
|
|
1651
|
-
ns,
|
|
1652
|
-
verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
|
|
1653
|
-
};
|
|
1654
|
-
})];
|
|
1655
|
-
_explainAggregate_decorators = [op((0, logger_1.mongoLogId)(1_001_000_177), ([ns, , , executionOptions]) => {
|
|
1656
|
-
return {
|
|
1657
|
-
ns,
|
|
1658
|
-
verbosity: executionOptions?.explainVerbosity || mongodb_1.ExplainVerbosity.executionStats,
|
|
1659
|
-
};
|
|
1660
|
-
})];
|
|
1661
|
-
_fetchShardKey_decorators = [op((0, logger_1.mongoLogId)(1_001_000_381))];
|
|
1662
|
-
_indexes_decorators = [op((0, logger_1.mongoLogId)(1_001_000_047))];
|
|
1663
|
-
_instance_decorators = [op((0, logger_1.mongoLogId)(1_001_000_024), (_, instanceData) => {
|
|
1664
|
-
if (instanceData) {
|
|
1665
|
-
return {
|
|
1666
|
-
serverVersion: instanceData.build.version,
|
|
1667
|
-
genuineMongoDB: instanceData.genuineMongoDB,
|
|
1668
|
-
dataLake: instanceData.dataLake,
|
|
1669
|
-
featureCompatibilityVersion: instanceData.featureCompatibilityVersion,
|
|
1670
|
-
};
|
|
1714
|
+
}
|
|
1715
|
+
configuredKMSProviders() {
|
|
1716
|
+
return (0, instance_detail_helper_2.configuredKMSProviders)(this._connectionOptions.fleOptions?.autoEncryption);
|
|
1717
|
+
}
|
|
1718
|
+
_csfleLogInformation(fleOptions) {
|
|
1719
|
+
const kmsProviders = (0, instance_detail_helper_2.configuredKMSProviders)(fleOptions?.autoEncryption);
|
|
1720
|
+
if (kmsProviders.length === 0)
|
|
1721
|
+
return null;
|
|
1722
|
+
return {
|
|
1723
|
+
storeCredentials: fleOptions?.storeCredentials,
|
|
1724
|
+
encryptedFieldsMapNamespaces: Object.keys({
|
|
1725
|
+
...fleOptions?.autoEncryption?.encryptedFieldsMap,
|
|
1726
|
+
...fleOptions?.autoEncryption?.schemaMap,
|
|
1727
|
+
}),
|
|
1728
|
+
keyVaultNamespace: fleOptions?.autoEncryption?.keyVaultNamespace,
|
|
1729
|
+
kmsProviders,
|
|
1730
|
+
};
|
|
1731
|
+
}
|
|
1732
|
+
async createDataKey(provider, options) {
|
|
1733
|
+
const clientEncryption = this._getClientEncryption();
|
|
1734
|
+
return await clientEncryption.createDataKey(provider, options ?? {});
|
|
1735
|
+
}
|
|
1736
|
+
_getClientEncryption() {
|
|
1737
|
+
const crudClient = this._initializedClient('CRUD');
|
|
1738
|
+
const autoEncryptionOptions = crudClient.options.autoEncryption;
|
|
1739
|
+
const { proxyHost, proxyPort, proxyUsername, proxyPassword } = crudClient.options;
|
|
1740
|
+
return new mongodb_1.ClientEncryption(crudClient, {
|
|
1741
|
+
keyVaultNamespace: autoEncryptionOptions.keyVaultNamespace,
|
|
1742
|
+
kmsProviders: autoEncryptionOptions.kmsProviders,
|
|
1743
|
+
tlsOptions: autoEncryptionOptions.tlsOptions,
|
|
1744
|
+
proxyOptions: proxyHost
|
|
1745
|
+
? {
|
|
1746
|
+
proxyHost,
|
|
1747
|
+
proxyPort,
|
|
1748
|
+
proxyUsername,
|
|
1749
|
+
proxyPassword,
|
|
1671
1750
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
_createDataKey_decorators = [op((0, logger_1.mongoLogId)(1_001_000_123), ([provider]) => {
|
|
1707
|
-
return { provider };
|
|
1708
|
-
})];
|
|
1709
|
-
_listStreamProcessors_decorators = [op((0, logger_1.mongoLogId)(1_001_000_284))];
|
|
1710
|
-
_startStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_285))];
|
|
1711
|
-
_stopStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_286))];
|
|
1712
|
-
_dropStreamProcessor_decorators = [op((0, logger_1.mongoLogId)(1_001_000_287))];
|
|
1713
|
-
__esDecorate(_a, null, _collectionStats_decorators, { kind: "method", name: "collectionStats", static: false, private: false, access: { has: obj => "collectionStats" in obj, get: obj => obj.collectionStats }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1714
|
-
__esDecorate(_a, null, _collectionInfo_decorators, { kind: "method", name: "collectionInfo", static: false, private: false, access: { has: obj => "collectionInfo" in obj, get: obj => obj.collectionInfo }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1715
|
-
__esDecorate(_a, null, _killOp_decorators, { kind: "method", name: "killOp", static: false, private: false, access: { has: obj => "killOp" in obj, get: obj => obj.killOp }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1716
|
-
__esDecorate(_a, null, __connectionStatus_decorators, { kind: "method", name: "_connectionStatus", static: false, private: false, access: { has: obj => "_connectionStatus" in obj, get: obj => obj._connectionStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1717
|
-
__esDecorate(_a, null, _listCollections_decorators, { kind: "method", name: "listCollections", static: false, private: false, access: { has: obj => "listCollections" in obj, get: obj => obj.listCollections }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1718
|
-
__esDecorate(_a, null, _listDatabases_decorators, { kind: "method", name: "listDatabases", static: false, private: false, access: { has: obj => "listDatabases" in obj, get: obj => obj.listDatabases }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1719
|
-
__esDecorate(_a, null, _estimatedCount_decorators, { kind: "method", name: "estimatedCount", static: false, private: false, access: { has: obj => "estimatedCount" in obj, get: obj => obj.estimatedCount }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1720
|
-
__esDecorate(_a, null, _count_decorators, { kind: "method", name: "count", static: false, private: false, access: { has: obj => "count" in obj, get: obj => obj.count }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1721
|
-
__esDecorate(_a, null, _createCollection_decorators, { kind: "method", name: "createCollection", static: false, private: false, access: { has: obj => "createCollection" in obj, get: obj => obj.createCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1722
|
-
__esDecorate(_a, null, _createIndex_decorators, { kind: "method", name: "createIndex", static: false, private: false, access: { has: obj => "createIndex" in obj, get: obj => obj.createIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1723
|
-
__esDecorate(_a, null, _deleteOne_decorators, { kind: "method", name: "deleteOne", static: false, private: false, access: { has: obj => "deleteOne" in obj, get: obj => obj.deleteOne }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1724
|
-
__esDecorate(_a, null, _deleteMany_decorators, { kind: "method", name: "deleteMany", static: false, private: false, access: { has: obj => "deleteMany" in obj, get: obj => obj.deleteMany }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1725
|
-
__esDecorate(_a, null, _dropCollection_decorators, { kind: "method", name: "dropCollection", static: false, private: false, access: { has: obj => "dropCollection" in obj, get: obj => obj.dropCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1726
|
-
__esDecorate(_a, null, _renameCollection_decorators, { kind: "method", name: "renameCollection", static: false, private: false, access: { has: obj => "renameCollection" in obj, get: obj => obj.renameCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1727
|
-
__esDecorate(_a, null, _dropDatabase_decorators, { kind: "method", name: "dropDatabase", static: false, private: false, access: { has: obj => "dropDatabase" in obj, get: obj => obj.dropDatabase }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1728
|
-
__esDecorate(_a, null, _dropIndex_decorators, { kind: "method", name: "dropIndex", static: false, private: false, access: { has: obj => "dropIndex" in obj, get: obj => obj.dropIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1729
|
-
__esDecorate(_a, null, _isListSearchIndexesSupported_decorators, { kind: "method", name: "isListSearchIndexesSupported", static: false, private: false, access: { has: obj => "isListSearchIndexesSupported" in obj, get: obj => obj.isListSearchIndexesSupported }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1730
|
-
__esDecorate(_a, null, _getSearchIndexes_decorators, { kind: "method", name: "getSearchIndexes", static: false, private: false, access: { has: obj => "getSearchIndexes" in obj, get: obj => obj.getSearchIndexes }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1731
|
-
__esDecorate(_a, null, _createSearchIndex_decorators, { kind: "method", name: "createSearchIndex", static: false, private: false, access: { has: obj => "createSearchIndex" in obj, get: obj => obj.createSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1732
|
-
__esDecorate(_a, null, _updateSearchIndex_decorators, { kind: "method", name: "updateSearchIndex", static: false, private: false, access: { has: obj => "updateSearchIndex" in obj, get: obj => obj.updateSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1733
|
-
__esDecorate(_a, null, _dropSearchIndex_decorators, { kind: "method", name: "dropSearchIndex", static: false, private: false, access: { has: obj => "dropSearchIndex" in obj, get: obj => obj.dropSearchIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1734
|
-
__esDecorate(_a, null, _aggregateCursor_decorators, { kind: "method", name: "aggregateCursor", static: false, private: false, access: { has: obj => "aggregateCursor" in obj, get: obj => obj.aggregateCursor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1735
|
-
__esDecorate(_a, null, _aggregate_decorators, { kind: "method", name: "aggregate", static: false, private: false, access: { has: obj => "aggregate" in obj, get: obj => obj.aggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1736
|
-
__esDecorate(_a, null, _find_decorators, { kind: "method", name: "find", static: false, private: false, access: { has: obj => "find" in obj, get: obj => obj.find }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1737
|
-
__esDecorate(_a, null, _findCursor_decorators, { kind: "method", name: "findCursor", static: false, private: false, access: { has: obj => "findCursor" in obj, get: obj => obj.findCursor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1738
|
-
__esDecorate(_a, null, _findOneAndReplace_decorators, { kind: "method", name: "findOneAndReplace", static: false, private: false, access: { has: obj => "findOneAndReplace" in obj, get: obj => obj.findOneAndReplace }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1739
|
-
__esDecorate(_a, null, _findOneAndUpdate_decorators, { kind: "method", name: "findOneAndUpdate", static: false, private: false, access: { has: obj => "findOneAndUpdate" in obj, get: obj => obj.findOneAndUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1740
|
-
__esDecorate(_a, null, _updateOne_decorators, { kind: "method", name: "updateOne", static: false, private: false, access: { has: obj => "updateOne" in obj, get: obj => obj.updateOne }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1741
|
-
__esDecorate(_a, null, _replaceOne_decorators, { kind: "method", name: "replaceOne", static: false, private: false, access: { has: obj => "replaceOne" in obj, get: obj => obj.replaceOne }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1742
|
-
__esDecorate(_a, null, _explainFind_decorators, { kind: "method", name: "explainFind", static: false, private: false, access: { has: obj => "explainFind" in obj, get: obj => obj.explainFind }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1743
|
-
__esDecorate(_a, null, _explainAggregate_decorators, { kind: "method", name: "explainAggregate", static: false, private: false, access: { has: obj => "explainAggregate" in obj, get: obj => obj.explainAggregate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1744
|
-
__esDecorate(_a, null, _fetchShardKey_decorators, { kind: "method", name: "fetchShardKey", static: false, private: false, access: { has: obj => "fetchShardKey" in obj, get: obj => obj.fetchShardKey }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1745
|
-
__esDecorate(_a, null, _indexes_decorators, { kind: "method", name: "indexes", static: false, private: false, access: { has: obj => "indexes" in obj, get: obj => obj.indexes }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1746
|
-
__esDecorate(_a, null, _instance_decorators, { kind: "method", name: "instance", static: false, private: false, access: { has: obj => "instance" in obj, get: obj => obj.instance }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1747
|
-
__esDecorate(_a, null, _insertOne_decorators, { kind: "method", name: "insertOne", static: false, private: false, access: { has: obj => "insertOne" in obj, get: obj => obj.insertOne }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1748
|
-
__esDecorate(_a, null, _insertMany_decorators, { kind: "method", name: "insertMany", static: false, private: false, access: { has: obj => "insertMany" in obj, get: obj => obj.insertMany }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1749
|
-
__esDecorate(_a, null, _updateCollection_decorators, { kind: "method", name: "updateCollection", static: false, private: false, access: { has: obj => "updateCollection" in obj, get: obj => obj.updateCollection }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1750
|
-
__esDecorate(_a, null, _currentOp_decorators, { kind: "method", name: "currentOp", static: false, private: false, access: { has: obj => "currentOp" in obj, get: obj => obj.currentOp }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1751
|
-
__esDecorate(_a, null, _serverStatus_decorators, { kind: "method", name: "serverStatus", static: false, private: false, access: { has: obj => "serverStatus" in obj, get: obj => obj.serverStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1752
|
-
__esDecorate(_a, null, _top_decorators, { kind: "method", name: "top", static: false, private: false, access: { has: obj => "top" in obj, get: obj => obj.top }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1753
|
-
__esDecorate(_a, null, _createView_decorators, { kind: "method", name: "createView", static: false, private: false, access: { has: obj => "createView" in obj, get: obj => obj.createView }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1754
|
-
__esDecorate(_a, null, _databaseStats_decorators, { kind: "method", name: "databaseStats", static: false, private: false, access: { has: obj => "databaseStats" in obj, get: obj => obj.databaseStats }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1755
|
-
__esDecorate(_a, null, _previewUpdate_decorators, { kind: "method", name: "previewUpdate", static: false, private: false, access: { has: obj => "previewUpdate" in obj, get: obj => obj.previewUpdate }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1756
|
-
__esDecorate(_a, null, _createDataKey_decorators, { kind: "method", name: "createDataKey", static: false, private: false, access: { has: obj => "createDataKey" in obj, get: obj => obj.createDataKey }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1757
|
-
__esDecorate(_a, null, _listStreamProcessors_decorators, { kind: "method", name: "listStreamProcessors", static: false, private: false, access: { has: obj => "listStreamProcessors" in obj, get: obj => obj.listStreamProcessors }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1758
|
-
__esDecorate(_a, null, _startStreamProcessor_decorators, { kind: "method", name: "startStreamProcessor", static: false, private: false, access: { has: obj => "startStreamProcessor" in obj, get: obj => obj.startStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1759
|
-
__esDecorate(_a, null, _stopStreamProcessor_decorators, { kind: "method", name: "stopStreamProcessor", static: false, private: false, access: { has: obj => "stopStreamProcessor" in obj, get: obj => obj.stopStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1760
|
-
__esDecorate(_a, null, _dropStreamProcessor_decorators, { kind: "method", name: "dropStreamProcessor", static: false, private: false, access: { has: obj => "dropStreamProcessor" in obj, get: obj => obj.dropStreamProcessor }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1761
|
-
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1762
|
-
})(),
|
|
1763
|
-
(() => {
|
|
1764
|
-
const assertNoExtraProps = (
|
|
1765
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1766
|
-
_cls) => {
|
|
1751
|
+
: undefined,
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
async getUpdatedSecrets() {
|
|
1755
|
+
if (!this._state)
|
|
1756
|
+
return {};
|
|
1757
|
+
return {
|
|
1758
|
+
oidc: {
|
|
1759
|
+
serializedState: await this._state.oidcPlugin.serialize(),
|
|
1760
|
+
},
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
async listStreamProcessors(filter) {
|
|
1764
|
+
const adminDb = this._database('admin', 'CRUD');
|
|
1765
|
+
const { streamProcessors } = await (0, run_command_1.runCommand)(adminDb, {
|
|
1766
|
+
listStreamProcessors: 1,
|
|
1767
|
+
filter,
|
|
1768
|
+
});
|
|
1769
|
+
return streamProcessors;
|
|
1770
|
+
}
|
|
1771
|
+
async startStreamProcessor(name) {
|
|
1772
|
+
const adminDb = this._database('admin', 'CRUD');
|
|
1773
|
+
await (0, run_command_1.runCommand)(adminDb, { startStreamProcessor: name });
|
|
1774
|
+
}
|
|
1775
|
+
async stopStreamProcessor(name) {
|
|
1776
|
+
const adminDb = this._database('admin', 'CRUD');
|
|
1777
|
+
await (0, run_command_1.runCommand)(adminDb, { stopStreamProcessor: name });
|
|
1778
|
+
}
|
|
1779
|
+
async dropStreamProcessor(name) {
|
|
1780
|
+
const adminDb = this._database('admin', 'CRUD');
|
|
1781
|
+
await (0, run_command_1.runCommand)(adminDb, { dropStreamProcessor: name });
|
|
1782
|
+
}
|
|
1783
|
+
static {
|
|
1784
|
+
const assertNoExtraProps = (_cls) => {
|
|
1767
1785
|
// Checking that we are not exposing anything unexpected on our data service
|
|
1768
1786
|
// implementation. This file will not compile if there are more public methods
|
|
1769
1787
|
// on the DataServiceImpl than DataService interface allows
|
|
1770
1788
|
};
|
|
1771
|
-
assertNoExtraProps(
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1789
|
+
assertNoExtraProps(this);
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1774
1792
|
})();
|
|
1775
1793
|
exports.DataServiceImpl = DataServiceImpl;
|
|
1776
1794
|
function isTransactionAbortError(err) {
|