Skip to content

Commit f1837bf

Browse files
Use timeoutcontext for state machine execute()
1 parent 17649e1 commit f1837bf

File tree

3 files changed

+38
-27
lines changed

3 files changed

+38
-27
lines changed

src/client-side-encryption/state_machine.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { type MongoCryptContext, type MongoCryptKMSRequest } from 'mongodb-clien
33
import * as net from 'net';
44
import * as tls from 'tls';
55

6+
import { type FindOptions } from '../beta';
67
import {
78
type BSONSerializeOptions,
89
deserialize,
@@ -11,6 +12,7 @@ import {
1112
serialize
1213
} from '../bson';
1314
import { type ProxyOptions } from '../cmap/connection';
15+
import { CursorTimeoutContext } from '../cursor/abstract_cursor';
1416
import { getSocks, type SocksLib } from '../deps';
1517
import { MongoOperationTimeoutError } from '../error';
1618
import { type MongoClient, type MongoClientOptions } from '../mongo_client';
@@ -524,9 +526,7 @@ export class StateMachine {
524526
.listCollections(filter, {
525527
promoteLongs: false,
526528
promoteValues: false,
527-
...(timeoutContext?.csotEnabled()
528-
? { timeoutMS: timeoutContext?.remainingTimeMS, timeoutMode: 'cursorLifetime' }
529-
: {})
529+
timeoutContext: timeoutContext && new CursorTimeoutContext(timeoutContext, Symbol())
530530
})
531531
.toArray();
532532

@@ -582,12 +582,9 @@ export class StateMachine {
582582
return client
583583
.db(dbName)
584584
.collection<DataKey>(collectionName, { readConcern: { level: 'majority' } })
585-
.find(
586-
deserialize(filter),
587-
timeoutContext?.csotEnabled()
588-
? { timeoutMS: timeoutContext?.remainingTimeMS, timeoutMode: 'cursorLifetime' }
589-
: {}
590-
)
585+
.find(deserialize(filter), {
586+
timeoutContext: timeoutContext && new CursorTimeoutContext(timeoutContext, Symbol())
587+
})
591588
.toArray();
592589
}
593590
}

src/operations/list_collections.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Binary, Document } from '../bson';
22
import { CursorResponse } from '../cmap/wire_protocol/responses';
3-
import { type CursorTimeoutMode } from '../cursor/abstract_cursor';
3+
import { type AbstractCursorOptions, type CursorTimeoutMode } from '../cursor/abstract_cursor';
44
import type { Db } from '../db';
55
import type { Server } from '../sdam/server';
66
import type { ClientSession } from '../sessions';
@@ -10,7 +10,9 @@ import { CommandOperation, type CommandOperationOptions } from './command';
1010
import { Aspect, defineAspects } from './operation';
1111

1212
/** @public */
13-
export interface ListCollectionsOptions extends Omit<CommandOperationOptions, 'writeConcern'> {
13+
export interface ListCollectionsOptions
14+
extends Omit<CommandOperationOptions, 'writeConcern'>,
15+
Pick<AbstractCursorOptions, 'timeoutContext'> {
1416
/** Since 4.0: If true, will only return the collection name in the response, and will omit additional info */
1517
nameOnly?: boolean;
1618
/** Since 4.0: If true and nameOnly is true, allows a user without the required privilege (i.e. listCollections action on the database) to run the command when access control is enforced. */

test/unit/client-side-encryption/state_machine.test.ts

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ import {
1616
BSON,
1717
Collection,
1818
CSOTTimeoutContext,
19+
CursorTimeoutContext,
20+
type FindOptions,
1921
Int32,
22+
type ListCollectionsOptions,
2023
Long,
2124
MongoClient,
2225
serialize,
@@ -484,26 +487,29 @@ describe('StateMachine', function () {
484487
});
485488

486489
context('when StateMachine.fetchKeys() is passed a `CSOTimeoutContext`', function () {
487-
it('collection.find runs with its timeoutMS property set to remainingTimeMS', async function () {
488-
const timeoutContext = new CSOTTimeoutContext({
490+
it('collection.find uses the provided timeout context', async function () {
491+
const context = new CSOTTimeoutContext({
489492
timeoutMS: 500,
490493
serverSelectionTimeoutMS: 30000
491494
});
492-
await sleep(300);
495+
493496
await stateMachine
494-
.fetchKeys(client, 'keyVault', BSON.serialize({ a: 1 }), timeoutContext)
497+
.fetchKeys(client, 'keyVault', BSON.serialize({ a: 1 }), context)
495498
.catch(e => squashError(e));
496-
expect(findSpy.getCalls()[0].args[1].timeoutMS).to.not.be.undefined;
497-
expect(findSpy.getCalls()[0].args[1].timeoutMS).to.be.lessThanOrEqual(205);
499+
500+
const { timeoutContext } = findSpy.getCalls()[0].args[1] as FindOptions;
501+
expect(timeoutContext).to.be.instanceOf(CursorTimeoutContext);
502+
expect(timeoutContext.timeoutContext).to.equal(context);
498503
});
499504
});
500505

501506
context('when StateMachine.fetchKeys() is not passed a `CSOTimeoutContext`', function () {
502-
it('collection.find runs with an undefined timeoutMS property', async function () {
507+
it('a timeoutContext is not provided to the find cursor', async function () {
503508
await stateMachine
504509
.fetchKeys(client, 'keyVault', BSON.serialize({ a: 1 }))
505510
.catch(e => squashError(e));
506-
expect(findSpy.getCalls()[0].args[1].timeoutMS).to.be.undefined;
511+
const { timeoutContext } = findSpy.getCalls()[0].args[1] as FindOptions;
512+
expect(timeoutContext).to.be.undefined;
507513
});
508514
});
509515
});
@@ -564,29 +570,35 @@ describe('StateMachine', function () {
564570
context(
565571
'when StateMachine.fetchCollectionInfo() is passed a `CSOTimeoutContext`',
566572
function () {
567-
it('listCollections runs with its timeoutMS property set to remainingTimeMS', async function () {
568-
const timeoutContext = new CSOTTimeoutContext({
573+
it('listCollections uses the provided timeoutContext', async function () {
574+
const context = new CSOTTimeoutContext({
569575
timeoutMS: 500,
570576
serverSelectionTimeoutMS: 30000
571577
});
572-
await sleep(300);
578+
573579
await stateMachine
574-
.fetchCollectionInfo(client, 'keyVault', BSON.serialize({ a: 1 }), timeoutContext)
580+
.fetchCollectionInfo(client, 'keyVault', BSON.serialize({ a: 1 }), context)
575581
.catch(e => squashError(e));
576-
expect(listCollectionsSpy.getCalls()[0].args[1].timeoutMS).to.not.be.undefined;
577-
expect(listCollectionsSpy.getCalls()[0].args[1].timeoutMS).to.be.lessThanOrEqual(205);
582+
583+
const { timeoutContext } = listCollectionsSpy.getCalls()[0]
584+
.args[1] as ListCollectionsOptions;
585+
expect(timeoutContext).to.be.instanceOf(CursorTimeoutContext);
586+
expect(timeoutContext.timeoutContext).to.equal(context);
578587
});
579588
}
580589
);
581590

582591
context(
583592
'when StateMachine.fetchCollectionInfo() is not passed a `CSOTimeoutContext`',
584593
function () {
585-
it('listCollections runs with an undefined timeoutMS property', async function () {
594+
it('no timeoutContext is provided to listCollections', async function () {
586595
await stateMachine
587596
.fetchCollectionInfo(client, 'keyVault', BSON.serialize({ a: 1 }))
588597
.catch(e => squashError(e));
589-
expect(listCollectionsSpy.getCalls()[0].args[1].timeoutMS).to.be.undefined;
598+
599+
const { timeoutContext } = listCollectionsSpy.getCalls()[0]
600+
.args[1] as ListCollectionsOptions;
601+
expect(timeoutContext).to.be.undefined;
590602
});
591603
}
592604
);

0 commit comments

Comments
 (0)