mongodb-data-service 21.10.0 → 21.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -22
- package/lib/connect-mongo-client.d.ts +11 -0
- package/lib/connect-mongo-client.js +88 -0
- package/lib/connect-mongo-client.js.map +1 -0
- package/lib/connect.js +2 -15
- package/lib/connect.js.map +1 -1
- package/lib/connection-info.d.ts +12 -0
- package/lib/connection-info.js +3 -0
- package/lib/connection-info.js.map +1 -0
- package/lib/connection-options.d.ts +2 -10
- package/lib/connection-secrets.d.ts +13 -0
- package/lib/connection-secrets.js +96 -0
- package/lib/connection-secrets.js.map +1 -0
- package/lib/connection-storage.d.ts +6 -0
- package/lib/connection-storage.js +45 -0
- package/lib/connection-storage.js.map +1 -0
- package/lib/connection-title.d.ts +2 -0
- package/lib/connection-title.js +25 -0
- package/lib/connection-title.js.map +1 -0
- package/lib/data-service.d.ts +62 -18
- package/lib/data-service.js +784 -75
- package/lib/data-service.js.map +1 -1
- package/lib/index.d.ts +8 -1
- package/lib/index.js +15 -1
- package/lib/index.js.map +1 -1
- package/lib/instance-detail-helper.d.ts +78 -32
- package/lib/instance-detail-helper.js +144 -433
- package/lib/instance-detail-helper.js.map +1 -1
- package/lib/{legacy-connection-model.d.ts → legacy/legacy-connection-model.d.ts} +25 -8
- package/lib/legacy/legacy-connection-model.js +203 -0
- package/lib/legacy/legacy-connection-model.js.map +1 -0
- package/lib/redact.d.ts +4 -1
- package/lib/redact.js +23 -11
- package/lib/redact.js.map +1 -1
- package/lib/run-command.d.ts +209 -0
- package/lib/run-command.js +11 -0
- package/lib/run-command.js.map +1 -0
- package/lib/ssh-tunnel.d.ts +5 -0
- package/lib/ssh-tunnel.js +73 -0
- package/lib/ssh-tunnel.js.map +1 -0
- package/lib/types.d.ts +2 -95
- package/package.json +26 -22
- package/lib/.esm-wrapper.mjs +0 -3
- package/lib/legacy-connect.d.ts +0 -7
- package/lib/legacy-connect.js +0 -97
- package/lib/legacy-connect.js.map +0 -1
- package/lib/legacy-connection-model.js +0 -62
- package/lib/legacy-connection-model.js.map +0 -1
- package/lib/native-client.d.ts +0 -92
- package/lib/native-client.js +0 -640
- package/lib/native-client.js.map +0 -1
package/lib/data-service.js
CHANGED
|
@@ -2,165 +2,874 @@
|
|
|
2
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const util_1 = require("util");
|
|
7
|
+
const async_1 = __importDefault(require("async"));
|
|
8
|
+
const compass_logging_1 = __importDefault(require("@mongodb-js/compass-logging"));
|
|
5
9
|
const events_1 = require("events");
|
|
6
|
-
const
|
|
10
|
+
const lodash_1 = require("lodash");
|
|
11
|
+
const mongodb_connection_string_url_1 = __importDefault(require("mongodb-connection-string-url"));
|
|
12
|
+
const instance_detail_helper_1 = require("./instance-detail-helper");
|
|
13
|
+
const redact_1 = require("./redact");
|
|
14
|
+
const connect_mongo_client_1 = __importDefault(require("./connect-mongo-client"));
|
|
15
|
+
const get_port_1 = __importDefault(require("get-port"));
|
|
16
|
+
const run_command_1 = require("./run-command");
|
|
17
|
+
const { fetch: getIndexes } = require('mongodb-index-model');
|
|
18
|
+
const parseNamespace = require('mongodb-ns');
|
|
19
|
+
const { log, mongoLogId, debug } = compass_logging_1.default('COMPASS-DATA-SERVICE');
|
|
20
|
+
function uniqueBy(values, key) {
|
|
21
|
+
return Array.from(new Map(values.map((val) => [val[key], val])).values());
|
|
22
|
+
}
|
|
23
|
+
let id = 0;
|
|
7
24
|
class DataService extends events_1.EventEmitter {
|
|
8
|
-
constructor(
|
|
25
|
+
constructor(connectionOptions) {
|
|
9
26
|
super();
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
27
|
+
this._isConnecting = false;
|
|
28
|
+
this._lastSeenTopology = null;
|
|
29
|
+
this._isWritable = false;
|
|
30
|
+
this._isMongos = false;
|
|
31
|
+
this._id = id++;
|
|
32
|
+
this._connectionOptions = connectionOptions;
|
|
33
|
+
}
|
|
34
|
+
getMongoClientConnectionOptions() {
|
|
35
|
+
return this._mongoClientConnectionOptions;
|
|
36
|
+
}
|
|
37
|
+
_logCtx() {
|
|
38
|
+
return `Connection ${this._id}`;
|
|
22
39
|
}
|
|
23
40
|
getConnectionOptions() {
|
|
24
|
-
return this.
|
|
41
|
+
return this._connectionOptions;
|
|
42
|
+
}
|
|
43
|
+
getConnectionString() {
|
|
44
|
+
return new mongodb_connection_string_url_1.default(this._connectionOptions.connectionString);
|
|
45
|
+
}
|
|
46
|
+
getReadPreference() {
|
|
47
|
+
return this._initializedClient.readPreference;
|
|
25
48
|
}
|
|
26
49
|
collection(ns, options, callback) {
|
|
27
|
-
|
|
50
|
+
async_1.default.parallel({
|
|
51
|
+
stats: this.collectionStats.bind(this, this._databaseName(ns), this._collectionName(ns)),
|
|
52
|
+
indexes: this.indexes.bind(this, ns, options),
|
|
53
|
+
}, (error, coll) => {
|
|
54
|
+
if (error) {
|
|
55
|
+
return callback(this._translateMessage(error));
|
|
56
|
+
}
|
|
57
|
+
callback(null, this._buildCollectionDetail(ns, coll));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
collections(databaseName, callback) {
|
|
61
|
+
if (databaseName === 'system') {
|
|
62
|
+
return callback(null, []);
|
|
63
|
+
}
|
|
64
|
+
this._collectionNames(databaseName, (error, names) => {
|
|
65
|
+
if (error) {
|
|
66
|
+
return callback(this._translateMessage(error));
|
|
67
|
+
}
|
|
68
|
+
async_1.default.parallel((names || []).map((name) => {
|
|
69
|
+
return (done) => {
|
|
70
|
+
this.collectionStats(databaseName, name, done);
|
|
71
|
+
};
|
|
72
|
+
}), callback);
|
|
73
|
+
});
|
|
28
74
|
}
|
|
29
75
|
collectionStats(databaseName, collectionName, callback) {
|
|
30
|
-
this.
|
|
76
|
+
const logop = this._startLogOp(mongoLogId(1001000031), 'Fetching collection info', { ns: `${databaseName}.${collectionName}` });
|
|
77
|
+
const db = this._initializedClient.db(databaseName);
|
|
78
|
+
db.command({ collStats: collectionName, verbose: true }, (error, data) => {
|
|
79
|
+
logop(error);
|
|
80
|
+
if (error && !error.message.includes('is a view, not a collection')) {
|
|
81
|
+
return callback(this._translateMessage(error));
|
|
82
|
+
}
|
|
83
|
+
callback(null, this._buildCollectionStats(databaseName, collectionName, data || {}));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async collectionInfo(dbName, collName) {
|
|
87
|
+
try {
|
|
88
|
+
const [collInfo] = await this.listCollections(dbName, { name: collName });
|
|
89
|
+
return collInfo !== null && collInfo !== void 0 ? collInfo : null;
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
throw this._translateMessage(err);
|
|
93
|
+
}
|
|
31
94
|
}
|
|
32
95
|
command(databaseName, comm, callback) {
|
|
33
|
-
this.
|
|
96
|
+
const db = this._initializedClient.db(databaseName);
|
|
97
|
+
db.command(comm, (error, result) => {
|
|
98
|
+
if (error) {
|
|
99
|
+
return callback(this._translateMessage(error));
|
|
100
|
+
}
|
|
101
|
+
callback(null, result);
|
|
102
|
+
});
|
|
34
103
|
}
|
|
35
104
|
isWritable() {
|
|
36
|
-
return this.
|
|
105
|
+
return this._isWritable;
|
|
37
106
|
}
|
|
38
107
|
isMongos() {
|
|
39
|
-
return this.
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
this.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
108
|
+
return this._isMongos;
|
|
109
|
+
}
|
|
110
|
+
async connectionStatus() {
|
|
111
|
+
const logop = this._startLogOp(mongoLogId(1001000100), 'Running connectionStatus');
|
|
112
|
+
try {
|
|
113
|
+
const adminDb = this._initializedClient.db('admin');
|
|
114
|
+
const result = await run_command_1.runCommand(adminDb, {
|
|
115
|
+
connectionStatus: 1,
|
|
116
|
+
showPrivileges: true,
|
|
117
|
+
});
|
|
118
|
+
logop(null);
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
logop(e);
|
|
123
|
+
throw e;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async _getPrivilegesOrFallback(privileges = null) {
|
|
127
|
+
if (privileges) {
|
|
128
|
+
return privileges;
|
|
129
|
+
}
|
|
130
|
+
const { authInfo: { authenticatedUserPrivileges }, } = await this.connectionStatus();
|
|
131
|
+
return authenticatedUserPrivileges;
|
|
132
|
+
}
|
|
133
|
+
async listCollections(databaseName, filter = {}, { nameOnly, privileges = null, } = {}) {
|
|
134
|
+
const logop = this._startLogOp(mongoLogId(1001000032), 'Running listCollections', { db: databaseName, nameOnly: nameOnly !== null && nameOnly !== void 0 ? nameOnly : false });
|
|
135
|
+
const db = this._initializedClient.db(databaseName);
|
|
136
|
+
const listCollections = async () => {
|
|
137
|
+
try {
|
|
138
|
+
return await db.listCollections(filter, { nameOnly }).toArray();
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
log.warn(mongoLogId(1001000099), this._logCtx(), 'Failed to run listCollections', { message: err.message });
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const getCollectionsFromPrivileges = async () => {
|
|
146
|
+
const databases = instance_detail_helper_1.getPrivilegesByDatabaseAndCollection(await this._getPrivilegesOrFallback(privileges), ['find']);
|
|
147
|
+
return Object.keys(databases[databaseName] || {})
|
|
148
|
+
.filter(Boolean)
|
|
149
|
+
.map((name) => ({ name }));
|
|
150
|
+
};
|
|
151
|
+
try {
|
|
152
|
+
const [listedCollections, collectionsFromPrivileges] = await Promise.all([
|
|
153
|
+
listCollections(),
|
|
154
|
+
getCollectionsFromPrivileges(),
|
|
155
|
+
]);
|
|
156
|
+
const collections = uniqueBy([...collectionsFromPrivileges, ...listedCollections], 'name').map((coll) => instance_detail_helper_1.adaptCollectionInfo({ db: databaseName, ...coll }));
|
|
157
|
+
logop(null, { collectionsCount: collections.length });
|
|
158
|
+
return collections;
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
logop(err);
|
|
162
|
+
throw err;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async listDatabases({ nameOnly, privileges = null, } = {}) {
|
|
166
|
+
const logop = this._startLogOp(mongoLogId(1001000033), 'Running listDatabases', { nameOnly: nameOnly !== null && nameOnly !== void 0 ? nameOnly : false });
|
|
167
|
+
const adminDb = this._initializedClient.db('admin');
|
|
168
|
+
const listDatabases = async () => {
|
|
169
|
+
try {
|
|
170
|
+
const { databases } = await run_command_1.runCommand(adminDb, {
|
|
171
|
+
listDatabases: 1,
|
|
172
|
+
nameOnly,
|
|
173
|
+
});
|
|
174
|
+
return databases;
|
|
51
175
|
}
|
|
52
|
-
|
|
53
|
-
|
|
176
|
+
catch (err) {
|
|
177
|
+
log.warn(mongoLogId(1001000098), this._logCtx(), 'Failed to run listDatabases', { message: err.message });
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
const getDatabasesFromPrivileges = async () => {
|
|
182
|
+
const databases = instance_detail_helper_1.getPrivilegesByDatabaseAndCollection(await this._getPrivilegesOrFallback(privileges), ['find']);
|
|
183
|
+
return Object.keys(databases)
|
|
184
|
+
.filter(Boolean)
|
|
185
|
+
.map((name) => ({ name }));
|
|
186
|
+
};
|
|
187
|
+
try {
|
|
188
|
+
const [listedDatabases, databasesFromPrivileges] = await Promise.all([
|
|
189
|
+
listDatabases(),
|
|
190
|
+
getDatabasesFromPrivileges(),
|
|
191
|
+
]);
|
|
192
|
+
const databases = uniqueBy([...databasesFromPrivileges, ...listedDatabases], 'name').map((db) => instance_detail_helper_1.adaptDatabaseInfo({ db: db.name, ...db }));
|
|
193
|
+
logop(null, { databasesCount: databases.length });
|
|
194
|
+
return databases;
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
logop(err);
|
|
198
|
+
throw err;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async connect() {
|
|
202
|
+
if (this._client) {
|
|
203
|
+
debug('already connected');
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (this._isConnecting) {
|
|
207
|
+
debug('connect method called more than once');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
debug('connecting...');
|
|
211
|
+
this._isConnecting = true;
|
|
212
|
+
log.info(mongoLogId(1001000014), this._logCtx(), 'Connecting', {
|
|
213
|
+
url: redact_1.redactConnectionString(this._connectionOptions.connectionString),
|
|
54
214
|
});
|
|
215
|
+
try {
|
|
216
|
+
const tunnelLocalPort = this._connectionOptions.sshTunnel
|
|
217
|
+
? await get_port_1.default()
|
|
218
|
+
: 0;
|
|
219
|
+
const [client, tunnel, connectionOptions] = await connect_mongo_client_1.default(this._connectionOptions, this.setupListeners.bind(this), tunnelLocalPort);
|
|
220
|
+
const attr = {
|
|
221
|
+
isWritable: this.isWritable(),
|
|
222
|
+
isMongos: this.isMongos(),
|
|
223
|
+
};
|
|
224
|
+
log.info(mongoLogId(1001000015), this._logCtx(), 'Connected', attr);
|
|
225
|
+
debug('connected!', attr);
|
|
226
|
+
this._client = client;
|
|
227
|
+
this._tunnel = tunnel;
|
|
228
|
+
this._mongoClientConnectionOptions = connectionOptions;
|
|
229
|
+
}
|
|
230
|
+
finally {
|
|
231
|
+
this._isConnecting = false;
|
|
232
|
+
}
|
|
55
233
|
}
|
|
56
234
|
estimatedCount(ns, options, callback) {
|
|
57
|
-
this.
|
|
235
|
+
const logop = this._startLogOp(mongoLogId(1001000034), 'Running estimatedCount', { ns });
|
|
236
|
+
this._collection(ns).estimatedDocumentCount(options, (err, result) => {
|
|
237
|
+
logop(err, result);
|
|
238
|
+
callback(err, result);
|
|
239
|
+
});
|
|
58
240
|
}
|
|
59
241
|
count(ns, filter, options, callback) {
|
|
60
|
-
this.
|
|
242
|
+
const logop = this._startLogOp(mongoLogId(1001000035), 'Running countDocuments', { ns });
|
|
243
|
+
this._collection(ns).countDocuments(filter, options, (err, result) => {
|
|
244
|
+
logop(err, result);
|
|
245
|
+
callback(err, result);
|
|
246
|
+
});
|
|
61
247
|
}
|
|
62
248
|
createCollection(ns, options, callback) {
|
|
63
|
-
this.
|
|
249
|
+
const collectionName = this._collectionName(ns);
|
|
250
|
+
const db = this._initializedClient.db(this._databaseName(ns));
|
|
251
|
+
const logop = this._startLogOp(mongoLogId(1001000036), 'Running createCollection', { ns, options });
|
|
252
|
+
db.createCollection(collectionName, options, (error, result) => {
|
|
253
|
+
logop(error);
|
|
254
|
+
if (error) {
|
|
255
|
+
return callback(this._translateMessage(error));
|
|
256
|
+
}
|
|
257
|
+
callback(null, result);
|
|
258
|
+
});
|
|
64
259
|
}
|
|
65
260
|
createIndex(ns, spec, options, callback) {
|
|
66
|
-
this.
|
|
261
|
+
const logop = this._startLogOp(mongoLogId(1001000037), 'Running createIndex', { ns, spec, options });
|
|
262
|
+
this._collection(ns).createIndex(spec, options, (error, result) => {
|
|
263
|
+
logop(error);
|
|
264
|
+
if (error) {
|
|
265
|
+
return callback(this._translateMessage(error));
|
|
266
|
+
}
|
|
267
|
+
callback(null, result);
|
|
268
|
+
});
|
|
67
269
|
}
|
|
68
270
|
database(name, options, callback) {
|
|
69
|
-
this.
|
|
271
|
+
const asyncColls = util_1.promisify(this.collections.bind(this));
|
|
272
|
+
void Promise.all([this.databaseStats(name), asyncColls(name)]).then(([stats, collections]) => {
|
|
273
|
+
callback(null, this._buildDatabaseDetail(name, { stats, collections }));
|
|
274
|
+
}, (err) => {
|
|
275
|
+
callback(this._translateMessage(err));
|
|
276
|
+
});
|
|
70
277
|
}
|
|
71
278
|
deleteOne(ns, filter, options, callback) {
|
|
72
|
-
this.
|
|
279
|
+
const logop = this._startLogOp(mongoLogId(1001000038), 'Running deleteOne', { ns });
|
|
280
|
+
this._collection(ns).deleteOne(filter, options, (error, result) => {
|
|
281
|
+
logop(error, result);
|
|
282
|
+
if (error) {
|
|
283
|
+
return callback(this._translateMessage(error));
|
|
284
|
+
}
|
|
285
|
+
callback(null, result);
|
|
286
|
+
});
|
|
73
287
|
}
|
|
74
288
|
deleteMany(ns, filter, options, callback) {
|
|
75
|
-
this.
|
|
289
|
+
const logop = this._startLogOp(mongoLogId(1001000039), 'Running deleteMany', { ns });
|
|
290
|
+
this._collection(ns).deleteMany(filter, options, (error, result) => {
|
|
291
|
+
logop(error, result);
|
|
292
|
+
if (error) {
|
|
293
|
+
return callback(this._translateMessage(error));
|
|
294
|
+
}
|
|
295
|
+
callback(null, result);
|
|
296
|
+
});
|
|
76
297
|
}
|
|
77
|
-
disconnect(
|
|
78
|
-
|
|
298
|
+
async disconnect() {
|
|
299
|
+
var _a, _b;
|
|
300
|
+
log.info(mongoLogId(1001000016), this._logCtx(), 'Disconnecting');
|
|
301
|
+
try {
|
|
302
|
+
await ((_a = this._client) === null || _a === void 0 ? void 0 : _a.close(true).catch((err) => debug('failed to close MongoClient', err)));
|
|
303
|
+
await ((_b = this._tunnel) === null || _b === void 0 ? void 0 : _b.close().catch((err) => debug('failed to close tunnel', err)));
|
|
304
|
+
}
|
|
305
|
+
finally {
|
|
306
|
+
this._cleanup();
|
|
307
|
+
log.info(mongoLogId(1001000017), this._logCtx(), 'Fully closed');
|
|
308
|
+
}
|
|
79
309
|
}
|
|
80
310
|
dropCollection(ns, callback) {
|
|
81
|
-
this.
|
|
311
|
+
const logop = this._startLogOp(mongoLogId(1001000059), 'Running dropCollection', { ns });
|
|
312
|
+
this._collection(ns).drop((error, result) => {
|
|
313
|
+
logop(error, result);
|
|
314
|
+
if (error) {
|
|
315
|
+
return callback(this._translateMessage(error));
|
|
316
|
+
}
|
|
317
|
+
callback(null, result);
|
|
318
|
+
});
|
|
82
319
|
}
|
|
83
320
|
dropDatabase(name, callback) {
|
|
84
|
-
this.
|
|
321
|
+
const logop = this._startLogOp(mongoLogId(1001000040), 'Running dropDatabase', { db: name });
|
|
322
|
+
this._initializedClient
|
|
323
|
+
.db(this._databaseName(name))
|
|
324
|
+
.dropDatabase((error, result) => {
|
|
325
|
+
logop(error, result);
|
|
326
|
+
if (error) {
|
|
327
|
+
return callback(this._translateMessage(error));
|
|
328
|
+
}
|
|
329
|
+
callback(null, result);
|
|
330
|
+
});
|
|
85
331
|
}
|
|
86
332
|
dropIndex(ns, name, callback) {
|
|
87
|
-
this.
|
|
333
|
+
const logop = this._startLogOp(mongoLogId(1001000060), 'Running dropIndex', { ns, name });
|
|
334
|
+
this._collection(ns).dropIndex(name, (error, result) => {
|
|
335
|
+
logop(error, result);
|
|
336
|
+
if (error) {
|
|
337
|
+
return callback(this._translateMessage(error));
|
|
338
|
+
}
|
|
339
|
+
callback(null, result);
|
|
340
|
+
});
|
|
88
341
|
}
|
|
89
342
|
aggregate(ns, pipeline, options, callback) {
|
|
90
|
-
|
|
343
|
+
log.info(mongoLogId(1001000041), this._logCtx(), 'Running aggregation', {
|
|
344
|
+
ns,
|
|
345
|
+
stages: pipeline.map((stage) => Object.keys(stage)[0]),
|
|
346
|
+
});
|
|
347
|
+
if (typeof options === 'function') {
|
|
348
|
+
callback = options;
|
|
349
|
+
options = undefined;
|
|
350
|
+
}
|
|
351
|
+
const cursor = this._collection(ns).aggregate(pipeline, options);
|
|
352
|
+
if (lodash_1.isFunction(callback)) {
|
|
353
|
+
process.nextTick(callback, null, cursor);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
return cursor;
|
|
91
357
|
}
|
|
92
358
|
find(ns, filter, options, callback) {
|
|
93
|
-
this.
|
|
359
|
+
const logop = this._startLogOp(mongoLogId(1001000042), 'Running find', {
|
|
360
|
+
ns,
|
|
361
|
+
});
|
|
362
|
+
const cursor = this._collection(ns).find(filter, options);
|
|
363
|
+
cursor.toArray((error, documents) => {
|
|
364
|
+
logop(error);
|
|
365
|
+
if (error) {
|
|
366
|
+
return callback(this._translateMessage(error));
|
|
367
|
+
}
|
|
368
|
+
callback(null, documents);
|
|
369
|
+
});
|
|
94
370
|
}
|
|
95
371
|
fetch(ns, filter, options) {
|
|
96
|
-
|
|
372
|
+
const logop = this._startLogOp(mongoLogId(1001000043), 'Running raw find', { ns });
|
|
373
|
+
return this._collection(ns).find(filter, options);
|
|
97
374
|
}
|
|
98
375
|
findOneAndReplace(ns, filter, replacement, options, callback) {
|
|
99
|
-
this.
|
|
376
|
+
const logop = this._startLogOp(mongoLogId(1001000044), 'Running findOneAndReplace', { ns });
|
|
377
|
+
this._collection(ns).findOneAndReplace(filter, replacement, options, (error, result) => {
|
|
378
|
+
logop(error);
|
|
379
|
+
if (error) {
|
|
380
|
+
return callback(this._translateMessage(error));
|
|
381
|
+
}
|
|
382
|
+
callback(null, result.value);
|
|
383
|
+
});
|
|
100
384
|
}
|
|
101
385
|
findOneAndUpdate(ns, filter, update, options, callback) {
|
|
102
|
-
this.
|
|
386
|
+
const logop = this._startLogOp(mongoLogId(1001000045), 'Running findOneAndUpdate', { ns });
|
|
387
|
+
this._collection(ns).findOneAndUpdate(filter, update, options, (error, result) => {
|
|
388
|
+
logop(error);
|
|
389
|
+
if (error) {
|
|
390
|
+
return callback(this._translateMessage(error));
|
|
391
|
+
}
|
|
392
|
+
callback(null, result.value);
|
|
393
|
+
});
|
|
103
394
|
}
|
|
104
395
|
explain(ns, filter, options, callback) {
|
|
105
|
-
this.
|
|
396
|
+
const logop = this._startLogOp(mongoLogId(1001000046), 'Running find explain', { ns });
|
|
397
|
+
this._collection(ns)
|
|
398
|
+
.find(filter, options)
|
|
399
|
+
.explain((error, explanation) => {
|
|
400
|
+
logop(error);
|
|
401
|
+
if (error) {
|
|
402
|
+
return callback(this._translateMessage(error));
|
|
403
|
+
}
|
|
404
|
+
callback(null, explanation);
|
|
405
|
+
});
|
|
106
406
|
}
|
|
107
407
|
indexes(ns, options, callback) {
|
|
108
|
-
this.
|
|
408
|
+
const logop = this._startLogOp(mongoLogId(1001000047), 'Listing indexes', { ns });
|
|
409
|
+
getIndexes(this._initializedClient, ns, (error, data) => {
|
|
410
|
+
logop(error);
|
|
411
|
+
if (error) {
|
|
412
|
+
return callback(this._translateMessage(error));
|
|
413
|
+
}
|
|
414
|
+
callback(null, data);
|
|
415
|
+
});
|
|
109
416
|
}
|
|
110
|
-
instance(
|
|
111
|
-
|
|
417
|
+
async instance() {
|
|
418
|
+
try {
|
|
419
|
+
const instanceData = await instance_detail_helper_1.getInstance(this._initializedClient);
|
|
420
|
+
log.info(mongoLogId(1001000024), this._logCtx(), 'Fetched instance information', {
|
|
421
|
+
serverVersion: instanceData.build.version,
|
|
422
|
+
genuineMongoDB: instanceData.genuineMongoDB,
|
|
423
|
+
dataLake: instanceData.dataLake,
|
|
424
|
+
featureCompatibilityVersion: instanceData.featureCompatibilityVersion,
|
|
425
|
+
});
|
|
426
|
+
return instanceData;
|
|
427
|
+
}
|
|
428
|
+
catch (err) {
|
|
429
|
+
throw this._translateMessage(err);
|
|
430
|
+
}
|
|
112
431
|
}
|
|
113
432
|
insertOne(ns, doc, options, callback) {
|
|
114
|
-
this.
|
|
433
|
+
const logop = this._startLogOp(mongoLogId(1001000048), 'Running insertOne', { ns });
|
|
434
|
+
this._collection(ns).insertOne(doc, options, (error, result) => {
|
|
435
|
+
logop(error, { acknowledged: result === null || result === void 0 ? void 0 : result.acknowledged });
|
|
436
|
+
if (error) {
|
|
437
|
+
return callback(this._translateMessage(error));
|
|
438
|
+
}
|
|
439
|
+
callback(null, result);
|
|
440
|
+
});
|
|
115
441
|
}
|
|
116
442
|
insertMany(ns, docs, options, callback) {
|
|
117
|
-
this.
|
|
443
|
+
const logop = this._startLogOp(mongoLogId(1001000049), 'Running insertOne', { ns });
|
|
444
|
+
this._collection(ns).insertMany(docs, options, (error, result) => {
|
|
445
|
+
logop(error, {
|
|
446
|
+
acknowledged: result === null || result === void 0 ? void 0 : result.acknowledged,
|
|
447
|
+
insertedCount: result === null || result === void 0 ? void 0 : result.insertedCount,
|
|
448
|
+
});
|
|
449
|
+
if (error) {
|
|
450
|
+
return callback(this._translateMessage(error));
|
|
451
|
+
}
|
|
452
|
+
callback(null, result);
|
|
453
|
+
});
|
|
118
454
|
}
|
|
119
455
|
putMany(ns, docs, options) {
|
|
120
|
-
return this.
|
|
456
|
+
return this._collection(ns).insertMany(docs, options);
|
|
121
457
|
}
|
|
122
458
|
updateCollection(ns, flags, callback) {
|
|
123
|
-
this.
|
|
459
|
+
const logop = this._startLogOp(mongoLogId(1001000050), 'Running updateCollection', { ns });
|
|
460
|
+
const collectionName = this._collectionName(ns);
|
|
461
|
+
const db = this._initializedClient.db(this._databaseName(ns));
|
|
462
|
+
const command = {
|
|
463
|
+
collMod: collectionName,
|
|
464
|
+
...flags,
|
|
465
|
+
};
|
|
466
|
+
db.command(command, (error, result) => {
|
|
467
|
+
logop(error, result);
|
|
468
|
+
if (error) {
|
|
469
|
+
return callback(this._translateMessage(error));
|
|
470
|
+
}
|
|
471
|
+
callback(null, result);
|
|
472
|
+
});
|
|
124
473
|
}
|
|
125
474
|
updateOne(ns, filter, update, options, callback) {
|
|
126
|
-
this.
|
|
475
|
+
const logop = this._startLogOp(mongoLogId(1001000051), 'Running updateOne', { ns });
|
|
476
|
+
this._collection(ns).updateOne(filter, update, options, (error, result) => {
|
|
477
|
+
logop(error, result);
|
|
478
|
+
if (error) {
|
|
479
|
+
return callback(this._translateMessage(error));
|
|
480
|
+
}
|
|
481
|
+
callback(null, result);
|
|
482
|
+
});
|
|
127
483
|
}
|
|
128
484
|
updateMany(ns, filter, update, options, callback) {
|
|
129
|
-
this.
|
|
485
|
+
const logop = this._startLogOp(mongoLogId(1001000052), 'Running updateMany', { ns });
|
|
486
|
+
this._collection(ns).updateMany(filter, update, options, (error, result) => {
|
|
487
|
+
logop(error, result);
|
|
488
|
+
if (error) {
|
|
489
|
+
return callback(this._translateMessage(error));
|
|
490
|
+
}
|
|
491
|
+
callback(null, result);
|
|
492
|
+
});
|
|
130
493
|
}
|
|
131
494
|
currentOp(includeAll, callback) {
|
|
132
|
-
this.
|
|
495
|
+
const logop = this._startLogOp(mongoLogId(1001000053), 'Running currentOp');
|
|
496
|
+
this._initializedClient
|
|
497
|
+
.db('admin')
|
|
498
|
+
.command({ currentOp: 1, $all: includeAll }, (error, result) => {
|
|
499
|
+
logop(error);
|
|
500
|
+
if (error) {
|
|
501
|
+
const logop = this._startLogOp(mongoLogId(1001000054), 'Searching $cmd.sys.inprog manually');
|
|
502
|
+
this._initializedClient
|
|
503
|
+
.db('admin')
|
|
504
|
+
.collection('$cmd.sys.inprog')
|
|
505
|
+
.findOne({ $all: includeAll }, (error2, result2) => {
|
|
506
|
+
logop(error2);
|
|
507
|
+
if (error2) {
|
|
508
|
+
return callback(this._translateMessage(error2));
|
|
509
|
+
}
|
|
510
|
+
callback(null, result2);
|
|
511
|
+
});
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
callback(null, result);
|
|
515
|
+
});
|
|
133
516
|
}
|
|
134
517
|
getLastSeenTopology() {
|
|
135
|
-
return this.
|
|
518
|
+
return this._lastSeenTopology;
|
|
136
519
|
}
|
|
137
520
|
serverstats(callback) {
|
|
138
|
-
this.
|
|
521
|
+
const logop = this._startLogOp(mongoLogId(1001000061), 'Running serverStats');
|
|
522
|
+
this._defaultDb.admin().serverStatus((error, result) => {
|
|
523
|
+
logop(error);
|
|
524
|
+
if (error) {
|
|
525
|
+
return callback(this._translateMessage(error));
|
|
526
|
+
}
|
|
527
|
+
callback(null, result);
|
|
528
|
+
});
|
|
139
529
|
}
|
|
140
530
|
top(callback) {
|
|
141
|
-
this.
|
|
531
|
+
const logop = this._startLogOp(mongoLogId(1001000062), 'Running top');
|
|
532
|
+
this._defaultDb.admin().command({ top: 1 }, (error, result) => {
|
|
533
|
+
logop(error);
|
|
534
|
+
if (error) {
|
|
535
|
+
return callback(this._translateMessage(error));
|
|
536
|
+
}
|
|
537
|
+
callback(null, result);
|
|
538
|
+
});
|
|
142
539
|
}
|
|
143
540
|
createView(name, sourceNs, pipeline, options, callback) {
|
|
144
|
-
this.
|
|
541
|
+
options.viewOn = this._collectionName(sourceNs);
|
|
542
|
+
options.pipeline = pipeline;
|
|
543
|
+
const logop = this._startLogOp(mongoLogId(1001000055), 'Running createView', {
|
|
544
|
+
name,
|
|
545
|
+
sourceNs,
|
|
546
|
+
stages: pipeline.map((stage) => Object.keys(stage)[0]),
|
|
547
|
+
options,
|
|
548
|
+
});
|
|
549
|
+
this._initializedClient
|
|
550
|
+
.db(this._databaseName(sourceNs))
|
|
551
|
+
.createCollection(name, options, (error, result) => {
|
|
552
|
+
logop(error, result);
|
|
553
|
+
if (error) {
|
|
554
|
+
return callback(this._translateMessage(error));
|
|
555
|
+
}
|
|
556
|
+
callback(null, result);
|
|
557
|
+
});
|
|
145
558
|
}
|
|
146
559
|
updateView(name, sourceNs, pipeline, options, callback) {
|
|
147
|
-
this.
|
|
560
|
+
options.viewOn = this._collectionName(sourceNs);
|
|
561
|
+
options.pipeline = pipeline;
|
|
562
|
+
const command = {
|
|
563
|
+
collMod: name,
|
|
564
|
+
...options,
|
|
565
|
+
};
|
|
566
|
+
const db = this._initializedClient.db(this._databaseName(sourceNs));
|
|
567
|
+
const logop = this._startLogOp(mongoLogId(1001000056), 'Running updateView', {
|
|
568
|
+
name,
|
|
569
|
+
sourceNs,
|
|
570
|
+
stages: pipeline.map((stage) => Object.keys(stage)[0]),
|
|
571
|
+
options,
|
|
572
|
+
});
|
|
573
|
+
db.command(command, (error, result) => {
|
|
574
|
+
logop(error, result);
|
|
575
|
+
if (error) {
|
|
576
|
+
return callback(this._translateMessage(error));
|
|
577
|
+
}
|
|
578
|
+
callback(null, result);
|
|
579
|
+
});
|
|
148
580
|
}
|
|
149
581
|
dropView(ns, callback) {
|
|
150
|
-
this.
|
|
151
|
-
}
|
|
152
|
-
sample(ns,
|
|
153
|
-
|
|
582
|
+
this.dropCollection(ns, callback);
|
|
583
|
+
}
|
|
584
|
+
sample(ns, { query, size, fields, } = {}, options = {}) {
|
|
585
|
+
const pipeline = [];
|
|
586
|
+
if (query && Object.keys(query).length > 0) {
|
|
587
|
+
pipeline.push({
|
|
588
|
+
$match: query,
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
pipeline.push({
|
|
592
|
+
$sample: {
|
|
593
|
+
size: size === 0 ? 0 : size || 1000,
|
|
594
|
+
},
|
|
595
|
+
});
|
|
596
|
+
if (fields && Object.keys(fields).length > 0) {
|
|
597
|
+
pipeline.push({
|
|
598
|
+
$project: fields,
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
return this.aggregate(ns, pipeline, {
|
|
602
|
+
allowDiskUse: true,
|
|
603
|
+
...options,
|
|
604
|
+
});
|
|
154
605
|
}
|
|
155
606
|
startSession() {
|
|
156
|
-
return this.
|
|
607
|
+
return this._initializedClient.startSession();
|
|
157
608
|
}
|
|
158
|
-
|
|
159
|
-
return this.
|
|
609
|
+
killSessions(sessions) {
|
|
610
|
+
return this._initializedClient.db('admin').command({
|
|
611
|
+
killSessions: Array.isArray(sessions)
|
|
612
|
+
? sessions.map((s) => s.id)
|
|
613
|
+
: [sessions.id],
|
|
614
|
+
});
|
|
160
615
|
}
|
|
161
616
|
isConnected() {
|
|
162
|
-
return this.
|
|
617
|
+
return !!this._client;
|
|
618
|
+
}
|
|
619
|
+
setupListeners(client) {
|
|
620
|
+
this._client = client;
|
|
621
|
+
if (client) {
|
|
622
|
+
client.on('serverDescriptionChanged', (evt) => {
|
|
623
|
+
var _a;
|
|
624
|
+
log.info(mongoLogId(1001000018), this._logCtx(), 'Server description changed', {
|
|
625
|
+
address: evt.address,
|
|
626
|
+
error: (_a = evt.newDescription.error) !== null && _a !== void 0 ? _a : null,
|
|
627
|
+
previousType: evt.previousDescription.type,
|
|
628
|
+
newType: evt.newDescription.type,
|
|
629
|
+
});
|
|
630
|
+
this.emit('serverDescriptionChanged', evt);
|
|
631
|
+
});
|
|
632
|
+
client.on('serverOpening', (evt) => {
|
|
633
|
+
log.info(mongoLogId(1001000019), this._logCtx(), 'Server opening', {
|
|
634
|
+
address: evt.address,
|
|
635
|
+
});
|
|
636
|
+
this.emit('serverOpening', evt);
|
|
637
|
+
});
|
|
638
|
+
client.on('serverClosed', (evt) => {
|
|
639
|
+
log.info(mongoLogId(1001000020), this._logCtx(), 'Server closed', {
|
|
640
|
+
address: evt.address,
|
|
641
|
+
});
|
|
642
|
+
this.emit('serverClosed', evt);
|
|
643
|
+
});
|
|
644
|
+
client.on('topologyOpening', (evt) => {
|
|
645
|
+
this.emit('topologyOpening', evt);
|
|
646
|
+
});
|
|
647
|
+
client.on('topologyClosed', (evt) => {
|
|
648
|
+
this.emit('topologyClosed', evt);
|
|
649
|
+
});
|
|
650
|
+
client.on('topologyDescriptionChanged', (evt) => {
|
|
651
|
+
this._isWritable = this._checkIsWritable(evt);
|
|
652
|
+
this._isMongos = this._checkIsMongos(evt);
|
|
653
|
+
const attr = {
|
|
654
|
+
isWritable: this.isWritable(),
|
|
655
|
+
isMongos: this.isMongos(),
|
|
656
|
+
previousType: evt.previousDescription.type,
|
|
657
|
+
newType: evt.newDescription.type,
|
|
658
|
+
};
|
|
659
|
+
log.info(mongoLogId(1001000021), this._logCtx(), 'Topology description changed', attr);
|
|
660
|
+
this._lastSeenTopology = evt.newDescription;
|
|
661
|
+
this.emit('topologyDescriptionChanged', evt);
|
|
662
|
+
});
|
|
663
|
+
const heartbeatStatusMap = new Map();
|
|
664
|
+
const isSignificantDurationChange = (before, after) => {
|
|
665
|
+
before = Math.max(before, 200);
|
|
666
|
+
after = Math.max(after, 200);
|
|
667
|
+
return Math.abs(Math.log2(before / after)) >= 1;
|
|
668
|
+
};
|
|
669
|
+
client.on('serverHeartbeatSucceeded', (evt) => {
|
|
670
|
+
const previousStatus = heartbeatStatusMap.get(evt.connectionId);
|
|
671
|
+
if (!previousStatus ||
|
|
672
|
+
previousStatus.failure ||
|
|
673
|
+
isSignificantDurationChange(previousStatus.duration, evt.duration)) {
|
|
674
|
+
heartbeatStatusMap.set(evt.connectionId, {
|
|
675
|
+
failure: null,
|
|
676
|
+
duration: evt.duration,
|
|
677
|
+
});
|
|
678
|
+
log.write({
|
|
679
|
+
s: 'D2',
|
|
680
|
+
id: mongoLogId(1001000022),
|
|
681
|
+
ctx: this._logCtx(),
|
|
682
|
+
msg: 'Server heartbeat succeeded',
|
|
683
|
+
attr: {
|
|
684
|
+
connectionId: evt.connectionId,
|
|
685
|
+
duration: evt.duration,
|
|
686
|
+
},
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
this.emit('serverHeartbeatSucceeded', evt);
|
|
690
|
+
});
|
|
691
|
+
client.on('serverHeartbeatFailed', (evt) => {
|
|
692
|
+
const previousStatus = heartbeatStatusMap.get(evt.connectionId);
|
|
693
|
+
if (!previousStatus ||
|
|
694
|
+
!previousStatus.failure ||
|
|
695
|
+
isSignificantDurationChange(previousStatus.duration, evt.duration)) {
|
|
696
|
+
heartbeatStatusMap.set(evt.connectionId, {
|
|
697
|
+
failure: evt.failure.message,
|
|
698
|
+
duration: evt.duration,
|
|
699
|
+
});
|
|
700
|
+
log.warn(mongoLogId(1001000023), this._logCtx(), 'Server heartbeat failed', {
|
|
701
|
+
connectionId: evt.connectionId,
|
|
702
|
+
duration: evt.duration,
|
|
703
|
+
failure: evt.failure.message,
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
this.emit('serverHeartbeatFailed', evt);
|
|
707
|
+
});
|
|
708
|
+
client.on('commandSucceeded', (evt) => {
|
|
709
|
+
const { address, connectionId, duration, commandName } = evt;
|
|
710
|
+
log.write({
|
|
711
|
+
s: 'D2',
|
|
712
|
+
id: mongoLogId(1001000029),
|
|
713
|
+
ctx: this._logCtx(),
|
|
714
|
+
msg: 'Driver command succeeded',
|
|
715
|
+
attr: {
|
|
716
|
+
address,
|
|
717
|
+
serverConnectionId: connectionId,
|
|
718
|
+
duration,
|
|
719
|
+
commandName,
|
|
720
|
+
},
|
|
721
|
+
});
|
|
722
|
+
});
|
|
723
|
+
client.on('commandFailed', (evt) => {
|
|
724
|
+
const { address, connectionId, duration, commandName, failure } = evt;
|
|
725
|
+
log.write({
|
|
726
|
+
s: 'D1',
|
|
727
|
+
id: mongoLogId(1001000030),
|
|
728
|
+
ctx: this._logCtx(),
|
|
729
|
+
msg: 'Driver command failed',
|
|
730
|
+
attr: {
|
|
731
|
+
address,
|
|
732
|
+
serverConnectionId: connectionId,
|
|
733
|
+
duration,
|
|
734
|
+
commandName,
|
|
735
|
+
failure: failure.message,
|
|
736
|
+
},
|
|
737
|
+
});
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
get _initializedClient() {
|
|
742
|
+
if (!this._client) {
|
|
743
|
+
throw new Error('client not yet initialized');
|
|
744
|
+
}
|
|
745
|
+
return this._client;
|
|
746
|
+
}
|
|
747
|
+
get _defaultDb() {
|
|
748
|
+
return this._initializedClient.db();
|
|
749
|
+
}
|
|
750
|
+
async databaseStats(name) {
|
|
751
|
+
const logop = this._startLogOp(mongoLogId(1001000057), 'Running databaseStats', { db: name });
|
|
752
|
+
try {
|
|
753
|
+
const db = this._initializedClient.db(name);
|
|
754
|
+
const stats = await run_command_1.runCommand(db, { dbStats: 1 });
|
|
755
|
+
const { _id, ...normalized } = instance_detail_helper_1.adaptDatabaseInfo(stats);
|
|
756
|
+
return normalized;
|
|
757
|
+
}
|
|
758
|
+
catch (err) {
|
|
759
|
+
logop(err);
|
|
760
|
+
throw this._translateMessage(err);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
_buildCollectionDetail(ns, data) {
|
|
764
|
+
return {
|
|
765
|
+
...data.stats,
|
|
766
|
+
_id: ns,
|
|
767
|
+
name: this._collectionName(ns),
|
|
768
|
+
database: this._databaseName(ns),
|
|
769
|
+
indexes: data.indexes,
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
_buildCollectionStats(databaseName, collectionName, data) {
|
|
773
|
+
var _a;
|
|
774
|
+
return {
|
|
775
|
+
ns: databaseName + '.' + collectionName,
|
|
776
|
+
name: collectionName,
|
|
777
|
+
database: databaseName,
|
|
778
|
+
is_capped: data.capped,
|
|
779
|
+
max: data.max,
|
|
780
|
+
is_power_of_two: data.userFlags === 1,
|
|
781
|
+
index_sizes: data.indexSizes,
|
|
782
|
+
document_count: (_a = data.count) !== null && _a !== void 0 ? _a : 0,
|
|
783
|
+
document_size: data.size,
|
|
784
|
+
storage_size: data.storageSize,
|
|
785
|
+
index_count: data.nindexes,
|
|
786
|
+
index_size: data.totalIndexSize,
|
|
787
|
+
padding_factor: data.paddingFactor,
|
|
788
|
+
extent_count: data.numExtents,
|
|
789
|
+
extent_last_size: data.lastExtentSize,
|
|
790
|
+
flags_user: data.userFlags,
|
|
791
|
+
max_document_size: data.maxSize,
|
|
792
|
+
size: data.size,
|
|
793
|
+
index_details: data.indexDetails || {},
|
|
794
|
+
wired_tiger: data.wiredTiger || {},
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
_buildDatabaseDetail(name, db) {
|
|
798
|
+
return {
|
|
799
|
+
_id: name,
|
|
800
|
+
name: name,
|
|
801
|
+
stats: db.stats,
|
|
802
|
+
collections: db.collections,
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
_collection(ns) {
|
|
806
|
+
return this._initializedClient
|
|
807
|
+
.db(this._databaseName(ns))
|
|
808
|
+
.collection(this._collectionName(ns));
|
|
809
|
+
}
|
|
810
|
+
_collectionNames(databaseName, callback) {
|
|
811
|
+
this.listCollections(databaseName, {}, { nameOnly: true }).then((collections) => {
|
|
812
|
+
const names = collections === null || collections === void 0 ? void 0 : collections.map((c) => c.name);
|
|
813
|
+
callback(null, names);
|
|
814
|
+
}, (error) => {
|
|
815
|
+
callback(this._translateMessage(error));
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
_collectionName(ns) {
|
|
819
|
+
return parseNamespace(ns).collection;
|
|
820
|
+
}
|
|
821
|
+
_databaseName(ns) {
|
|
822
|
+
return parseNamespace(ns).database;
|
|
823
|
+
}
|
|
824
|
+
_checkIsWritable(evt) {
|
|
825
|
+
return [...evt.newDescription.servers.values()].some((server) => server.isWritable);
|
|
826
|
+
}
|
|
827
|
+
_checkIsMongos(evt) {
|
|
828
|
+
return evt.newDescription.type === 'Sharded';
|
|
829
|
+
}
|
|
830
|
+
_translateMessage(error) {
|
|
831
|
+
if (typeof error === 'string') {
|
|
832
|
+
error = { message: error };
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
error.message = error.message || error.err || error.errmsg;
|
|
836
|
+
}
|
|
837
|
+
return error;
|
|
838
|
+
}
|
|
839
|
+
_cleanup() {
|
|
840
|
+
if (this._client) {
|
|
841
|
+
this._client.removeAllListeners();
|
|
842
|
+
}
|
|
843
|
+
this._client = undefined;
|
|
844
|
+
this._tunnel = undefined;
|
|
845
|
+
this._mongoClientConnectionOptions = undefined;
|
|
846
|
+
this._isWritable = false;
|
|
847
|
+
this._isMongos = false;
|
|
848
|
+
this._isConnecting = false;
|
|
849
|
+
}
|
|
850
|
+
_startLogOp(logId, op, attr = {}) {
|
|
851
|
+
return (error, result) => {
|
|
852
|
+
if (error) {
|
|
853
|
+
const { message } = this._translateMessage(error);
|
|
854
|
+
log.error(mongoLogId(1001000058), this._logCtx(), 'Failed to perform data service operation', {
|
|
855
|
+
op,
|
|
856
|
+
message,
|
|
857
|
+
...attr,
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
else {
|
|
861
|
+
if (result) {
|
|
862
|
+
attr = { ...attr, result };
|
|
863
|
+
}
|
|
864
|
+
if (Object.keys(attr).length > 0) {
|
|
865
|
+
log.info(logId, this._logCtx(), op, attr);
|
|
866
|
+
}
|
|
867
|
+
else {
|
|
868
|
+
log.info(logId, this._logCtx(), op);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
};
|
|
163
872
|
}
|
|
164
873
|
}
|
|
165
|
-
|
|
874
|
+
exports.default = DataService;
|
|
166
875
|
//# sourceMappingURL=data-service.js.map
|