Skip to content

Commit 4f1e18f

Browse files
authored
feat(shell-api): support hedge/tagSet in cursor.readPref MONGOSH-511 (#587)
1 parent ef3bfd4 commit 4f1e18f

File tree

13 files changed

+76
-50
lines changed

13 files changed

+76
-50
lines changed

packages/java-shell/src/main/kotlin/com/mongodb/mongosh/service/AdminServiceProvider.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.graalvm.polyglot.Value
77
*/
88
internal interface AdminServiceProvider {
99
fun listDatabases(database: String, options: Value?): Value
10+
fun readPreferenceFromOptions(options: Value?): Value
1011
fun getNewConnection(uri: String, options: Value?): Value
1112
fun getConnectionInfo(): Value
1213
fun authenticate(authDoc: Value): Value

packages/java-shell/src/main/kotlin/com/mongodb/mongosh/service/JavaServiceProvider.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,11 @@ internal class JavaServiceProvider(private val client: MongoClient,
447447
Left(NotImplementedError())
448448
}
449449

450+
@HostAccess.Export
451+
override fun readPreferenceFromOptions(options: Value?): Value = promise<Any?> {
452+
Left(NotImplementedError())
453+
}
454+
450455
@HostAccess.Export
451456
override fun getConnectionInfo(): Value = promise<Any?> {
452457
Left(NotImplementedError())
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
11
[ { "_id": <ObjectID>, "a": "a" }, { "_id": <ObjectID>, "a": "A" }, { "_id": <ObjectID>, "a": "\u00E1" } ]
2-
java.lang.Exception: MongoshUnimplementedError: [COMMON-90002] the tagSet argument is not yet supported.
3-
java.lang.Exception: MongoshUnimplementedError: [COMMON-90002] the tagSet argument is not yet supported.

packages/java-shell/src/test/resources/cursor/readPref.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ db.coll.find({a: "a"})
88
.collation({"locale": "en_US", strength: 1})
99
.readPref('nearest');
1010
// command
11-
db.coll.find({a: "a"})
12-
.collation({"locale": "en_US", strength: 1})
13-
.readPref("secondary", [{"region": "South"}]);
11+
//db.coll.find({a: "a"})
12+
// .collation({"locale": "en_US", strength: 1})
13+
// .readPref("secondary", [{"region": "South"}]);
1414
// command
15-
db.coll.find({a: "a"})
16-
.collation({"locale": "en_US", strength: 1})
17-
.readPref("secondary", [{"region": "South", "datacenter": "A"}, {}]);
15+
//db.coll.find({a: "a"})
16+
// .collation({"locale": "en_US", strength: 1})
17+
// .readPref("secondary", [{"region": "South", "datacenter": "A"}, {}]);
1818
// clear
1919
db.coll.drop();

packages/service-provider-core/src/admin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export default interface Admin {
9292
*
9393
* @param options
9494
*/
95-
resetConnectionOptions(options: Document): Promise<void>;
95+
resetConnectionOptions(options: MongoClientOptions): Promise<void>;
9696

9797
/**
9898
* Start a session.

packages/service-provider-core/src/all-transport-types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export type {
3535
FindAndModifyOptions,
3636
FindOperators,
3737
FindOptions,
38+
HedgeOptions,
3839
IndexDescription,
3940
InsertManyResult,
4041
InsertOneOptions,
@@ -50,12 +51,14 @@ export type {
5051
ReadConcernLevelId,
5152
ReadPreference,
5253
ReadPreferenceLike,
54+
ReadPreferenceFromOptions,
5355
ReadPreferenceModeId,
5456
RenameOptions,
5557
ReplaceOptions,
5658
ResumeToken,
5759
RunCommandOptions,
5860
ServerSessionId,
61+
TagSet,
5962
TransactionOptions,
6063
UpdateOptions,
6164
UpdateResult,

packages/service-provider-core/src/readable.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import type {
1111
ListIndexesOptions,
1212
AggregationCursor,
1313
FindCursor,
14-
DbOptions
14+
DbOptions,
15+
ReadPreferenceFromOptions,
16+
ReadPreferenceLike
1517
} from './all-transport-types';
1618
import { ChangeStream, ChangeStreamOptions } from './all-transport-types';
1719

@@ -199,6 +201,11 @@ export default interface Readable {
199201
options?: ListCollectionsOptions,
200202
dbOptions?: DbOptions): Promise<Document[]>;
201203

204+
/**
205+
* Create a ReadPreference object from a set of options
206+
*/
207+
readPreferenceFromOptions(options?: Omit<ReadPreferenceFromOptions, 'session'>): ReadPreferenceLike | undefined;
208+
202209
/**
203210
* Get all the collection statistics.
204211
*

packages/service-provider-server/src/cli-service-provider.integration.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ describe('CliServiceProvider [integration]', function() {
9696
it('resets the MongoClient', async() => {
9797
const mongoClientBefore = serviceProvider.mongoClient;
9898
await serviceProvider.resetConnectionOptions({
99-
readPreference: { mode: 'secondaryPreferred' }
99+
readPreference: 'secondaryPreferred'
100100
});
101101
expect(serviceProvider.mongoClient).to.not.equal(mongoClientBefore);
102102
expect(serviceProvider.getReadPreference().mode).to.equal('secondaryPreferred');

packages/service-provider-server/src/cli-service-provider.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import {
1616
Decimal128,
1717
BSONSymbol,
1818
ClientMetadata,
19-
Topology
19+
Topology,
20+
ReadPreferenceFromOptions,
21+
ReadPreferenceLike
2022
} from 'mongodb';
2123

2224
import {
@@ -1104,21 +1106,16 @@ class CliServiceProvider extends ServiceProviderCore implements ServiceProvider
11041106
return this.mongoClient.writeConcern;
11051107
}
11061108

1109+
readPreferenceFromOptions(options?: Omit<ReadPreferenceFromOptions, 'session'>): ReadPreferenceLike | undefined {
1110+
return ReadPreference.fromOptions(options);
1111+
}
1112+
11071113
/**
11081114
* For instances where a user wants to set a option that requires a new MongoClient.
11091115
*
11101116
* @param options
11111117
*/
1112-
async resetConnectionOptions(options: Document): Promise<void> {
1113-
// NOTE: we keep all the original options and just overwrite the passed.
1114-
if (options.readPreference !== undefined) {
1115-
const pr = new ReadPreference(
1116-
options.readPreference.mode,
1117-
options.readPreference.tagSet,
1118-
options.hedgeOptions
1119-
);
1120-
options.readPreference = pr;
1121-
}
1118+
async resetConnectionOptions(options: MongoClientOptions): Promise<void> {
11221119
const clientOptions = processDriverOptions({
11231120
...this.initialOptions,
11241121
...options

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -442,29 +442,32 @@ describe('Cursor', () => {
442442
describe('#readPref', () => {
443443
let spCursor: StubbedInstance<ServiceProviderCursor>;
444444
let shellApiCursor;
445+
let fromOptionsStub;
445446
const value = 'primary';
447+
const tagSet = [{ nodeType: 'ANALYTICS' }];
446448

447449
beforeEach(() => {
448450
spCursor = stubInterface<ServiceProviderCursor>();
449451
shellApiCursor = new Cursor(mongo, spCursor);
452+
fromOptionsStub = sinon.stub();
453+
fromOptionsStub.callsFake(input => input);
454+
mongo._serviceProvider = {
455+
readPreferenceFromOptions: fromOptionsStub
456+
};
450457
});
451458

452459
it('fluidly sets the read preference', () => {
453460
expect(shellApiCursor.readPref(value)).to.equal(shellApiCursor);
454461
expect(spCursor.withReadPreference).to.have.been.calledWith(value);
455462
});
456463

457-
it('throws MongoshUnimplementedError if tagset is passed', () => {
458-
try {
459-
shellApiCursor.readPref(value, []);
460-
expect.fail('expected error');
461-
} catch (e) {
462-
expect(e).to.be.instanceOf(MongoshUnimplementedError);
463-
expect(e.message).to.contain('the tagSet argument is not yet supported.');
464-
expect(e.code).to.equal(CommonErrors.NotImplemented);
465-
expect(e.metadata?.driverCaused).to.equal(true);
466-
expect(e.metadata?.api).to.equal('Cursor.readPref#tagSet');
467-
}
464+
it('fluidly sets the read preference with tagSet and hedge options', () => {
465+
expect(shellApiCursor.readPref(value, tagSet, { enabled: true })).to.equal(shellApiCursor);
466+
expect(spCursor.withReadPreference).to.have.been.calledWith({
467+
readPreference: value,
468+
readPreferenceTags: tagSet,
469+
hedge: { enabled: true }
470+
});
468471
});
469472
});
470473

0 commit comments

Comments
 (0)