Skip to content

Commit 14cd413

Browse files
authored
chore(shell-api): make coll.find() an async function (#1063)
This is in preparation for MONGOSH-537, where it will make things a bit easier if we have the liberty to make async calls inside all methods that perform interactions with the database (i.e. fetching `_baseOptions` can be an async operation). Also tighten up some types in the tests along with this.
1 parent af309dd commit 14cd413

13 files changed

+109
-108
lines changed

packages/shell-api/src/collection.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,11 @@ export default class Collection extends ShellApiWithMongoClass {
405405
*
406406
* @returns {Cursor} The promise of the cursor.
407407
*/
408+
// eslint-disable-next-line @typescript-eslint/require-await
408409
@returnType('Cursor')
409410
@apiVersions([1])
410-
find(query?: Document, projection?: Document, options: FindOptions = {}): Cursor {
411+
@returnsPromise
412+
async find(query?: Document, projection?: Document, options: FindOptions = {}): Promise<Cursor> {
411413
if (projection) {
412414
options.projection = projection;
413415
}

packages/shell-api/src/database.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,8 +1351,8 @@ export default class Database extends ShellApiWithMongoClass {
13511351
result.usedMB = olStats.size / (1024 * 1024);
13521352
result.usedMB = Math.ceil(result.usedMB * 100) / 100;
13531353

1354-
const first = await ol.find().sort({ $natural: 1 }).limit(1).tryNext();
1355-
const last = await ol.find().sort({ $natural: -1 }).limit(1).tryNext();
1354+
const first = await (await ol.find()).sort({ $natural: 1 }).limit(1).tryNext();
1355+
const last = await (await ol.find()).sort({ $natural: -1 }).limit(1).tryNext();
13561356
if (first === null || last === null) {
13571357
throw new MongoshRuntimeError(
13581358
'objects not found in local.oplog.$main -- is this a new and empty db instance?',

packages/shell-api/src/explainable.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('Explainable', () => {
2626
it('attributes', () => {
2727
expect(signatures.Explainable.attributes.find).to.deep.equal({
2828
type: 'function',
29-
returnsPromise: false,
29+
returnsPromise: true,
3030
deprecated: false,
3131
returnType: 'ExplainableCursor',
3232
platforms: ALL_PLATFORMS,
@@ -103,15 +103,15 @@ describe('Explainable', () => {
103103
describe('find', () => {
104104
let cursorStub;
105105
let explainResult;
106-
beforeEach(() => {
106+
beforeEach(async() => {
107107
explainResult = { ok: 1 };
108108

109109
const cursorSpy = {
110110
explain: sinon.spy(() => explainResult)
111111
} as unknown;
112-
collection.find = sinon.spy(() => (cursorSpy as Cursor));
112+
collection.find = sinon.spy(() => Promise.resolve(cursorSpy as Cursor));
113113

114-
cursorStub = explainable.find(
114+
cursorStub = await explainable.find(
115115
{ query: 1 },
116116
{ projection: 1 }
117117
);

packages/shell-api/src/explainable.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,11 @@ export default class Explainable extends ShellApiWithMongoClass {
8585

8686
@returnType('ExplainableCursor')
8787
@apiVersions([1])
88-
find(query?: Document, projection?: Document): ExplainableCursor {
88+
@returnsPromise
89+
async find(query?: Document, projection?: Document): Promise<ExplainableCursor> {
8990
this._emitExplainableApiCall('find', { query, projection });
9091

91-
const cursor = this._collection.find(query, projection);
92+
const cursor = await this._collection.find(query, projection);
9293
return new ExplainableCursor(this._mongo, cursor, this._verbosity);
9394
}
9495

packages/shell-api/src/field-level-encryption.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,29 +287,29 @@ describe('Field Level Encryption', () => {
287287
});
288288
});
289289
describe('getKey', () => {
290-
it('calls find on key coll', () => {
290+
it('calls find on key coll', async() => {
291291
const c = { cursor: 1 } as any;
292292
sp.find.returns(c);
293-
const result = keyVault.getKey(KEY_ID);
293+
const result = await keyVault.getKey(KEY_ID);
294294
expect(sp.find).to.have.been.calledOnceWithExactly(DB, COLL, { _id: KEY_ID }, {});
295295
expect(result._cursor).to.deep.equal(c);
296296
});
297297
});
298298
describe('getKeyByAltName', () => {
299-
it('calls find on key coll', () => {
299+
it('calls find on key coll', async() => {
300300
const c = { cursor: 1 } as any;
301301
const keyaltname = 'abc';
302302
sp.find.returns(c);
303-
const result = keyVault.getKeyByAltName(keyaltname);
303+
const result = await keyVault.getKeyByAltName(keyaltname);
304304
expect(sp.find).to.have.been.calledOnceWithExactly(DB, COLL, { keyAltNames: keyaltname }, {});
305305
expect(result._cursor).to.deep.equal(c);
306306
});
307307
});
308308
describe('getKeys', () => {
309-
it('calls find on key coll', () => {
309+
it('calls find on key coll', async() => {
310310
const c = { cursor: 1 } as any;
311311
sp.find.returns(c);
312-
const result = keyVault.getKeys();
312+
const result = await keyVault.getKeys();
313313
expect(sp.find).to.have.been.calledOnceWithExactly(DB, COLL, {}, {});
314314
expect(result._cursor).to.deep.equal(c);
315315
});

packages/shell-api/src/field-level-encryption.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,21 +179,24 @@ export class KeyVault extends ShellApiWithMongoClass {
179179

180180
@returnType('Cursor')
181181
@apiVersions([1])
182-
getKey(keyId: BinaryType): Cursor {
182+
@returnsPromise
183+
async getKey(keyId: BinaryType): Promise<Cursor> {
183184
assertArgsDefinedType([keyId], [true], 'KeyVault.getKey');
184185
return this._keyColl.find({ '_id': keyId });
185186
}
186187

187188
@returnType('Cursor')
188189
@apiVersions([1])
189-
getKeyByAltName(keyAltName: string): Cursor {
190+
@returnsPromise
191+
async getKeyByAltName(keyAltName: string): Promise<Cursor> {
190192
assertArgsDefinedType([keyAltName], ['string'], 'KeyVault.getKeyByAltName');
191193
return this._keyColl.find({ 'keyAltNames': keyAltName });
192194
}
193195

194196
@returnType('Cursor')
195197
@apiVersions([1])
196-
getKeys(): Cursor {
198+
@returnsPromise
199+
async getKeys(): Promise<Cursor> {
197200
return this._keyColl.find({});
198201
}
199202

packages/shell-api/src/helpers.ts

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export function processDigestPassword(
170170
* @param configDB
171171
* @param verbose
172172
*/
173-
export async function getPrintableShardStatus(db: Database, verbose: boolean): Promise<any> {
173+
export async function getPrintableShardStatus(db: Database, verbose: boolean): Promise<Document> {
174174
const result = {} as any; // use array to maintain order
175175

176176
// configDB is a DB object that contains the sharding metadata of interest.
@@ -185,8 +185,8 @@ export async function getPrintableShardStatus(db: Database, verbose: boolean): P
185185

186186
const [ version, shards, mostRecentMongos ] = await Promise.all([
187187
versionColl.findOne(),
188-
shardsColl.find().sort({ _id: 1 }).toArray(),
189-
mongosColl.find().sort({ ping: -1 }).limit(1).tryNext()
188+
shardsColl.find().then(cursor => cursor.sort({ _id: 1 }).toArray()),
189+
mongosColl.find().then(cursor => cursor.sort({ ping: -1 }).limit(1).tryNext())
190190
]);
191191
if (version === null) {
192192
throw new MongoshInvalidInputError(
@@ -228,8 +228,8 @@ export async function getPrintableShardStatus(db: Database, verbose: boolean): P
228228
};
229229

230230
if (verbose) {
231-
result[mongosAdjective] = await mongosColl
232-
.find(recentMongosQuery)
231+
result[mongosAdjective] = await (await mongosColl
232+
.find(recentMongosQuery))
233233
.sort({ ping: -1 })
234234
.toArray();
235235
} else {
@@ -277,7 +277,7 @@ export async function getPrintableShardStatus(db: Database, verbose: boolean): P
277277
(async(): Promise<void> => {
278278
// Output the list of active migrations
279279
type Lock = { _id: string; when: Date };
280-
const activeLocks: Lock[] = await configDB.getCollection('locks').find({ state: { $eq: 2 } }).toArray() as Lock[];
280+
const activeLocks: Lock[] = await (await configDB.getCollection('locks').find({ state: { $eq: 2 } })).toArray() as Lock[];
281281
if (activeLocks?.length > 0) {
282282
balancerRes['Collections with active migrations'] = activeLocks.map((lock) => {
283283
return `${lock._id} started at ${lock.when}`;
@@ -300,7 +300,7 @@ export async function getPrintableShardStatus(db: Database, verbose: boolean): P
300300

301301
if (versionHasActionlog) {
302302
// Review config.actionlog for errors
303-
const balErrs = await configDB.getCollection('actionlog').find({ what: 'balancer.round' }).sort({ time: -1 }).limit(5).toArray();
303+
const balErrs = await (await configDB.getCollection('actionlog').find({ what: 'balancer.round' })).sort({ time: -1 }).limit(5).toArray();
304304
const actionReport = { count: 0, lastErr: '', lastTime: ' ' };
305305
if (balErrs !== null) {
306306
balErrs.forEach((r: any) => {
@@ -393,7 +393,7 @@ export async function getPrintableShardStatus(db: Database, verbose: boolean): P
393393
const dbRes: any[] = [];
394394
result.databases = dbRes;
395395

396-
const databases = await configDB.getCollection('databases').find().sort({ name: 1 }).toArray();
396+
const databases = await (await configDB.getCollection('databases').find()).sort({ name: 1 }).toArray();
397397

398398
// Special case the config db, since it doesn't have a record in config.databases.
399399
databases.push({ '_id': 'config', 'primary': 'config', 'partitioned': true });
@@ -405,8 +405,8 @@ export async function getPrintableShardStatus(db: Database, verbose: boolean): P
405405
const escapeRegex = (string: string): string => {
406406
return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
407407
};
408-
const colls = await configDB.getCollection('collections')
409-
.find({ _id: new RegExp('^' + escapeRegex(db._id) + '\\.') })
408+
const colls = await (await configDB.getCollection('collections')
409+
.find({ _id: new RegExp('^' + escapeRegex(db._id) + '\\.') }))
410410
.sort({ _id: 1 })
411411
.toArray();
412412

@@ -441,45 +441,39 @@ export async function getPrintableShardStatus(db: Database, verbose: boolean): P
441441

442442
// NOTE: this will return the chunk info as a string, and will print ugly BSON
443443
if (totalChunks < 20 || verbose) {
444-
(await chunksColl.find(chunksCollMatch)
445-
.sort({ min: 1 }).toArray())
446-
.forEach((chunk: any) => {
447-
const c = {
448-
min: chunk.min,
449-
max: chunk.max,
450-
'on shard': chunk.shard,
451-
'last modified': chunk.lastmod
452-
} as any;
453-
// Displaying a full, multi-line output for each chunk is a bit verbose,
454-
// even if there are only a few chunks. Where supported, we use a custom
455-
// inspection function to inspect a copy of this object with an unlimited
456-
// line break length (i.e. all objects on a single line).
457-
Object.defineProperty(c, Symbol.for('nodejs.util.inspect.custom'), {
458-
value: function(depth: number, options: any): string {
459-
return inspect({ ...this }, { ...options, breakLength: Infinity });
460-
},
461-
writable: true,
462-
configurable: true
463-
});
464-
if (chunk.jumbo) c.jumbo = 'yes';
465-
chunksRes.push(c);
444+
for await (const chunk of (await chunksColl.find(chunksCollMatch)).sort({ min: 1 })) {
445+
const c = {
446+
min: chunk.min,
447+
max: chunk.max,
448+
'on shard': chunk.shard,
449+
'last modified': chunk.lastmod
450+
} as any;
451+
// Displaying a full, multi-line output for each chunk is a bit verbose,
452+
// even if there are only a few chunks. Where supported, we use a custom
453+
// inspection function to inspect a copy of this object with an unlimited
454+
// line break length (i.e. all objects on a single line).
455+
Object.defineProperty(c, Symbol.for('nodejs.util.inspect.custom'), {
456+
value: function(depth: number, options: any): string {
457+
return inspect({ ...this }, { ...options, breakLength: Infinity });
458+
},
459+
writable: true,
460+
configurable: true
466461
});
462+
if (chunk.jumbo) c.jumbo = 'yes';
463+
chunksRes.push(c);
464+
}
467465
} else {
468466
chunksRes.push('too many chunks to print, use verbose if you want to force print');
469467
}
470468

471469
const tagsRes: any[] = [];
472-
(await configDB.getCollection('tags')
473-
.find(chunksCollMatch)
474-
.sort({ min: 1 })
475-
.toArray())
476-
.forEach((tag: any) => {
477-
tagsRes.push({
478-
tag: tag.tag,
479-
min: tag.min,
480-
max: tag.max
481-
});
470+
for await (const tag of (await configDB.getCollection('tags').find(chunksCollMatch)).sort({ min: 1 })) {
471+
tagsRes.push({
472+
tag: tag.tag,
473+
min: tag.min,
474+
max: tag.max
482475
});
476+
}
483477
collRes.chunks = chunksRes;
484478
collRes.tags = tagsRes;
485479
return [coll._id, collRes];

0 commit comments

Comments
 (0)