Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions packages/i18n/src/locales/en_US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,13 @@ const translations: Catalog = {
example:
'db.collection.aggregate(pipeline, options).skip(offsetNumber)',
},
disableBlockWarnings: {
link: '',
description:
'Disables warnings for blocking operations on the cursor.',
example:
'db.collection.aggregate(pipeline, options).disableBlockWarnings()',
},
},
},
},
Expand Down Expand Up @@ -965,6 +972,17 @@ const translations: Catalog = {
description:
'This method is deprecated because because after closing a cursor, the remaining documents in the batch are no longer accessible. If you want to see if the cursor is closed use cursor.isClosed. If you want to see if there are documents left in the batch, use cursor.tryNext. This is a breaking change',
},
disableBlockWarnings: {
link: '',
description:
'Disables warnings for blocking operations on the cursor.',
},
batchSize: {
description: 'Not available on change streams',
},
maxTimeMS: {
description: 'Not available on change streams',
},
},
},
},
Expand Down Expand Up @@ -1260,6 +1278,13 @@ const translations: Catalog = {
example:
'db.collection.find(query, projection, options).toArray()',
},
disableBlockWarnings: {
link: '',
description:
'Disables warnings for blocking operations on the cursor.',
example:
'db.collection.find(query, projection, options).disableBlockWarnings()',
},
},
},
},
Expand Down Expand Up @@ -1839,6 +1864,11 @@ const translations: Catalog = {
description:
"If a document is in the cursor's batch it will be returned, otherwise null will be returned",
},
disableBlockWarnings: {
link: '',
description:
'Disables warnings for blocking operations on the cursor.',
},
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion packages/service-provider-core/src/cursors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
ResumeToken,
} from './all-transport-types';

interface ServiceProviderBaseCursor<TSchema = Document> {
export interface ServiceProviderBaseCursor<TSchema = Document> {
close(): Promise<void>;
hasNext(): Promise<boolean>;
next(): Promise<TSchema | null>;
Expand Down
1 change: 1 addition & 0 deletions packages/service-provider-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export { bson } from './bson-export';
export {
ServiceProviderAbstractCursor,
ServiceProviderAggregationCursor,
ServiceProviderBaseCursor,
ServiceProviderFindCursor,
ServiceProviderRunCommandCursor,
ServiceProviderChangeStream,
Expand Down
133 changes: 77 additions & 56 deletions packages/shell-api/src/abstract-cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,52 +11,25 @@ import type {
ServiceProviderFindCursor,
ServiceProviderAggregationCursor,
ServiceProviderRunCommandCursor,
ServiceProviderBaseCursor,
} from '@mongosh/service-provider-core';
import { asPrintable } from './enums';
import { CursorIterationResult } from './result';
import { iterate } from './helpers';

@shellApiClassNoHelp
export abstract class AbstractCursor<
CursorType extends
| ServiceProviderAggregationCursor
| ServiceProviderFindCursor
| ServiceProviderRunCommandCursor
export abstract class BaseCursor<
CursorType extends ServiceProviderBaseCursor
> extends ShellApiWithMongoClass {
_mongo: Mongo;
_cursor: CursorType;
_transform: ((doc: any) => any) | null;

_currentIterationResult: CursorIterationResult | null = null;
_transform: ((doc: any) => any) | null = null;
_blockingWarningDisabled = false;

constructor(mongo: Mongo, cursor: CursorType) {
super();
this._mongo = mongo;
this._cursor = cursor;
this._transform = null;
}

/**
* Internal method to determine what is printed for this class.
*/
async [asPrintable](): Promise<CursorIterationResult> {
return (
await toShellResult(this._currentIterationResult ?? (await this._it()))
).printable;
}

async _it(): Promise<CursorIterationResult> {
const results = (this._currentIterationResult =
new CursorIterationResult());
await iterate(results, this, await this._mongo._displayBatchSize());
results.cursorHasMore = !this.isExhausted();
return results;
}

@returnType('this')
batchSize(size: number): this {
this._cursor.batchSize(size);
return this;
}

@returnsPromise
Expand Down Expand Up @@ -136,24 +109,6 @@ export abstract class AbstractCursor<
return count;
}

@returnsPromise
async toArray(): Promise<Document[]> {
// toArray is always defined for driver cursors, but not necessarily
// in tests
if (
typeof this._cursor.toArray === 'function' &&
this._canDelegateIterationToUnderlyingCursor()
) {
return await this._cursor.toArray();
}

const result = [];
for await (const doc of this) {
result.push(doc);
}
return result;
}

@returnType('this')
pretty(): this {
return this;
Expand All @@ -170,12 +125,6 @@ export abstract class AbstractCursor<
return this;
}

@returnType('this')
maxTimeMS(value: number): this {
this._cursor.maxTimeMS(value);
return this;
}

@returnsPromise
async next(): Promise<Document | null> {
let result = await this._cursor.next();
Expand All @@ -185,6 +134,78 @@ export abstract class AbstractCursor<
return result;
}

disableBlockWarnings(): this {
this._blockingWarningDisabled = true;
return this;
}

abstract batchSize(size: number): this;
abstract toArray(): Promise<Document[]>;
abstract maxTimeMS(value: number): this;
abstract objsLeftInBatch(): number;
abstract _it(): Promise<CursorIterationResult>;
}

@shellApiClassNoHelp
export abstract class AbstractFiniteCursor<
CursorType extends
| ServiceProviderAggregationCursor
| ServiceProviderFindCursor
| ServiceProviderRunCommandCursor
> extends BaseCursor<CursorType> {
_currentIterationResult: CursorIterationResult | null = null;

constructor(mongo: Mongo, cursor: CursorType) {
super(mongo, cursor);
}

/**
* Internal method to determine what is printed for this class.
*/
async [asPrintable](): Promise<CursorIterationResult | string> {
return (
await toShellResult(this._currentIterationResult ?? (await this._it()))
).printable;
}

override async _it(): Promise<CursorIterationResult> {
const results = (this._currentIterationResult =
new CursorIterationResult());
await iterate(results, this, await this._mongo._displayBatchSize());
results.cursorHasMore = !this.isExhausted();
return results;
}

@returnType('this')
override batchSize(size: number): this {
this._cursor.batchSize(size);
return this;
}

@returnsPromise
override async toArray(): Promise<Document[]> {
// toArray is always defined for driver cursors, but not necessarily
// in tests
if (
typeof this._cursor.toArray === 'function' &&
this._canDelegateIterationToUnderlyingCursor()
) {
return await this._cursor.toArray();
}

const result = [];
for await (const doc of this) {
result.push(doc);
}
return result;
}

@returnType('this')
maxTimeMS(value: number): this {
this._cursor.maxTimeMS(value);
return this;
}

objsLeftInBatch(): number {
return this._cursor.bufferedCount();
}
Expand Down
4 changes: 2 additions & 2 deletions packages/shell-api/src/aggregate-or-find-cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import type {
ServiceProviderAggregationCursor,
} from '@mongosh/service-provider-core';
import { validateExplainableVerbosity, markAsExplainOutput } from './helpers';
import { AbstractCursor } from './abstract-cursor';
import { AbstractFiniteCursor } from './abstract-cursor';

@shellApiClassNoHelp
export abstract class AggregateOrFindCursor<
CursorType extends
| ServiceProviderAggregationCursor
| ServiceProviderFindCursor
> extends AbstractCursor<CursorType> {
> extends AbstractFiniteCursor<CursorType> {
@returnType('this')
projection(spec: Document): this {
this._cursor.project(spec);
Expand Down
29 changes: 23 additions & 6 deletions packages/shell-api/src/change-stream-cursor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,28 @@ describe('ChangeStreamCursor', function () {
);
expect(result).to.equal(1);
});
it('map() works', async function () {
cursor.map((doc) => ({ wrapped: doc }));
await coll.insertOne({ myDoc: 1 });
const result = await ensureResult(
100,
async () => await cursor.tryNext(),
(doc) => !!doc?.wrapped,
'tryNext to return a document'
);
expect(result.wrapped.fullDocument.myDoc).to.equal(1);
});
it('forEach() works', async function () {
await coll.insertOne({ myDoc: 1 });
let foundDoc = false;
await cursor.forEach((doc): boolean | void => {
if (doc?.fullDocument?.myDoc === 1) {
foundDoc = true;
return false;
}
});
expect(foundDoc).to.equal(true);
});
});
describe('database watch', function () {
beforeEach(async function () {
Expand Down Expand Up @@ -330,12 +352,7 @@ describe('ChangeStreamCursor', function () {
);
});

for (const name of [
'map',
'forEach',
'toArray',
'objsLeftInBatch',
] as const) {
for (const name of ['toArray', 'objsLeftInBatch', 'maxTimeMS'] as const) {
it(`${name} fails`, function () {
expect(() => cursor[name]()).to.throw(MongoshUnimplementedError);
});
Expand Down
Loading
Loading