Skip to content

Commit 59c5de2

Browse files
committed
feat: reimplement clone for find and aggregate cursors
NODE-2811
1 parent 8f24e65 commit 59c5de2

File tree

3 files changed

+84
-24
lines changed

3 files changed

+84
-24
lines changed

src/cursor/aggregation_cursor.ts

+10
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ export class AggregationCursor extends AbstractCursor {
4848
return this[kPipeline];
4949
}
5050

51+
/**
52+
* Returns a new uninitialized copy of this cursor, with options matching those that have been set on the current instance
53+
*/
54+
clone(): AggregationCursor {
55+
return new AggregationCursor(this[kParent], this.topology, this.namespace, this[kPipeline], {
56+
...this[kOptions],
57+
...this.cursorOptions
58+
});
59+
}
60+
5161
/** @internal */
5262
_initialize(session: ClientSession | undefined, callback: Callback<ExecutionResult>): void {
5363
const aggregateOperation = new AggregateOperation(this[kParent], this[kPipeline], {

src/cursor/find_cursor.ts

+10
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ export class FindCursor extends AbstractCursor {
4949
}
5050
}
5151

52+
/**
53+
* Returns a new uninitialized copy of this cursor, with options matching those that have been set on the current instance
54+
*/
55+
clone(): FindCursor {
56+
return new FindCursor(this.topology, this.namespace, this[kFilter], {
57+
...this[kBuiltOptions],
58+
...this.cursorOptions
59+
});
60+
}
61+
5262
/** @internal */
5363
_initialize(session: ClientSession | undefined, callback: Callback<ExecutionResult>): void {
5464
const findOperation = new FindOperation(undefined, this.namespace, this[kFilter], {

test/functional/abstract_cursor.test.js

+64-24
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ describe('AbstractCursor', function () {
2222
before(
2323
withClientV2((client, done) => {
2424
const docs = [{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }, { a: 5 }, { a: 6 }];
25-
const coll = client.db().collection('find_cursor');
25+
const coll = client.db().collection('abstract_cursor');
2626
const tryNextColl = client.db().collection('try_next');
2727
coll.drop(() => tryNextColl.drop(() => coll.insertMany(docs, done)));
2828
})
@@ -35,7 +35,7 @@ describe('AbstractCursor', function () {
3535
const commands = [];
3636
client.on('commandStarted', filterForCommands(['getMore'], commands));
3737

38-
const coll = client.db().collection('find_cursor');
38+
const coll = client.db().collection('abstract_cursor');
3939
const cursor = coll.find({}, { batchSize: 2 });
4040
this.defer(() => cursor.close());
4141

@@ -56,7 +56,7 @@ describe('AbstractCursor', function () {
5656
const commands = [];
5757
client.on('commandStarted', filterForCommands(['killCursors'], commands));
5858

59-
const coll = client.db().collection('find_cursor');
59+
const coll = client.db().collection('abstract_cursor');
6060
const cursor = coll.find({}, { batchSize: 2 });
6161
cursor.next(err => {
6262
expect(err).to.not.exist;
@@ -75,7 +75,7 @@ describe('AbstractCursor', function () {
7575
const commands = [];
7676
client.on('commandStarted', filterForCommands(['killCursors'], commands));
7777

78-
const coll = client.db().collection('find_cursor');
78+
const coll = client.db().collection('abstract_cursor');
7979
const cursor = coll.find({}, { batchSize: 2 });
8080
cursor.toArray(err => {
8181
expect(err).to.not.exist;
@@ -95,7 +95,7 @@ describe('AbstractCursor', function () {
9595
const commands = [];
9696
client.on('commandStarted', filterForCommands(['killCursors'], commands));
9797

98-
const coll = client.db().collection('find_cursor');
98+
const coll = client.db().collection('abstract_cursor');
9999
const cursor = coll.find({}, { batchSize: 2 });
100100
cursor.close(err => {
101101
expect(err).to.not.exist;
@@ -110,7 +110,7 @@ describe('AbstractCursor', function () {
110110
it(
111111
'should iterate each document in a cursor',
112112
withClientV2(function (client, done) {
113-
const coll = client.db().collection('find_cursor');
113+
const coll = client.db().collection('abstract_cursor');
114114
const cursor = coll.find({}, { batchSize: 2 });
115115

116116
const bag = [];
@@ -160,45 +160,85 @@ describe('AbstractCursor', function () {
160160
);
161161
});
162162

163-
context('#rewind', function () {
164-
beforeEach(
163+
context('#clone', function () {
164+
it(
165+
'should clone a find cursor',
165166
withClientV2(function (client, done) {
166-
const coll = client.db().collection('rewind');
167-
coll.drop(() => {
168-
coll.insertMany([{}, {}], err => {
167+
const coll = client.db().collection('abstract_cursor');
168+
const cursor = coll.find({});
169+
this.defer(() => cursor.close());
170+
171+
cursor.toArray((err, docs) => {
172+
expect(err).to.not.exist;
173+
expect(docs).to.have.length(6);
174+
expect(cursor).property('closed').to.be.true;
175+
176+
const clonedCursor = cursor.clone();
177+
this.defer(() => clonedCursor.close());
178+
179+
clonedCursor.toArray((err, docs) => {
180+
expect(err).to.not.exist;
181+
expect(docs).to.have.length(6);
182+
expect(clonedCursor).property('closed').to.be.true;
183+
done();
184+
});
185+
});
186+
})
187+
);
188+
189+
it(
190+
'should clone an aggregate cursor',
191+
withClientV2(function (client, done) {
192+
const coll = client.db().collection('abstract_cursor');
193+
const cursor = coll.aggregate([{ $match: {} }]);
194+
this.defer(() => cursor.close());
195+
196+
cursor.toArray((err, docs) => {
197+
expect(err).to.not.exist;
198+
expect(docs).to.have.length(6);
199+
expect(cursor).property('closed').to.be.true;
200+
201+
const clonedCursor = cursor.clone();
202+
this.defer(() => clonedCursor.close());
203+
204+
clonedCursor.toArray((err, docs) => {
169205
expect(err).to.not.exist;
206+
expect(docs).to.have.length(6);
207+
expect(clonedCursor).property('closed').to.be.true;
170208
done();
171209
});
172210
});
173211
})
174212
);
213+
});
175214

215+
context('#rewind', function () {
176216
it(
177217
'should rewind a cursor',
178218
withClientV2(function (client, done) {
179-
const coll = client.db().collection('rewind');
219+
const coll = client.db().collection('abstract_cursor');
180220
const cursor = coll.find({});
181221
this.defer(() => cursor.close());
182222

183223
cursor.toArray((err, docs) => {
184224
expect(err).to.not.exist;
185-
expect(docs).to.have.length(2);
225+
expect(docs).to.have.length(6);
186226

187227
cursor.rewind();
188228
cursor.toArray((err, docs) => {
189229
expect(err).to.not.exist;
190-
expect(docs).to.have.length(2);
230+
expect(docs).to.have.length(6);
191231

192232
done();
193233
});
194234
});
195235
})
196236
);
197237

198-
it(
199-
'should end an implicit session on rewind',
200-
withClientV2(function (client, done) {
201-
const coll = client.db().collection('rewind');
238+
it('should end an implicit session on rewind', {
239+
metadata: { requires: { mongodb: '>=3.6' } },
240+
test: withClientV2(function (client, done) {
241+
const coll = client.db().collection('abstract_cursor');
202242
const cursor = coll.find({}, { batchSize: 1 });
203243
this.defer(() => cursor.close());
204244

@@ -213,12 +253,12 @@ describe('AbstractCursor', function () {
213253
done();
214254
});
215255
})
216-
);
256+
});
217257

218-
it(
219-
'should not end an explicit session on rewind',
220-
withClientV2(function (client, done) {
221-
const coll = client.db().collection('rewind');
258+
it('should not end an explicit session on rewind', {
259+
metadata: { requires: { mongodb: '>=3.6' } },
260+
test: withClientV2(function (client, done) {
261+
const coll = client.db().collection('abstract_cursor');
222262
const session = client.startSession();
223263

224264
const cursor = coll.find({}, { batchSize: 1, session });
@@ -236,6 +276,6 @@ describe('AbstractCursor', function () {
236276
session.endSession(done);
237277
});
238278
})
239-
);
279+
});
240280
});
241281
});

0 commit comments

Comments
 (0)