Skip to content

Commit

Permalink
fix(NODE-3705): ReadPreference.fromOptions omitting hedge and maxStal…
Browse files Browse the repository at this point in the history
…enessSeconds when readPreference is a string (#3060)
  • Loading branch information
Bailey Pearson committed Dec 1, 2021
1 parent 7b00d0f commit b9fbac5
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 65 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Expand Up @@ -58,6 +58,7 @@
- Neal Beeken <<neal.beeken@mongodb.com>>
- Durran Jordan <<durran@gmail.com>>
- Daria Pardue <<daria.pardue@mongodb.com>>
- Bailey Pearson <<bailey.pearson@mongodb.com>>

## Community Types

Expand Down
5 changes: 4 additions & 1 deletion src/read_preference.ts
Expand Up @@ -156,7 +156,10 @@ export class ReadPreference {
}

if (typeof readPreference === 'string') {
return new ReadPreference(readPreference as ReadPreferenceMode, readPreferenceTags);
return new ReadPreference(readPreference as ReadPreferenceMode, readPreferenceTags, {
maxStalenessSeconds: options.maxStalenessSeconds,
hedge: options.hedge
});
} else if (!(readPreference instanceof ReadPreference) && typeof readPreference === 'object') {
const mode = readPreference.mode || readPreference.preference;
if (mode && typeof mode === 'string') {
Expand Down
64 changes: 0 additions & 64 deletions test/functional/readpreference.test.js
Expand Up @@ -14,70 +14,6 @@ describe('ReadPreference', function () {
return setupDatabase(this.configuration);
});

describe('::constructor', function () {
const maxStalenessSeconds = 1234;
const { PRIMARY, SECONDARY, NEAREST } = ReadPreference;
const TAGS = [{ loc: 'dc' }];

it('should accept (mode)', function () {
expect(new ReadPreference(PRIMARY)).to.be.an.instanceOf(ReadPreference);
});

it('should accept valid (mode, tags)', function () {
expect(new ReadPreference(PRIMARY, [])).to.be.an.instanceOf(ReadPreference);
const p0 = new ReadPreference(NEAREST, TAGS);
expect(p0.mode).to.equal(NEAREST);
});

it('should not accept invalid tags', function () {
expect(() => new ReadPreference(PRIMARY, 'invalid')).to.throw(
'ReadPreference tags must be an array'
);
expect(() => new ReadPreference(PRIMARY, { loc: 'dc' }, { maxStalenessSeconds })).to.throw(
'ReadPreference tags must be an array'
);
});

it('should accept (mode, options)', function () {
const p1 = new ReadPreference(SECONDARY, { maxStalenessSeconds });
expect(p1.mode).to.equal(SECONDARY);
expect(p1.maxStalenessSeconds).to.equal(maxStalenessSeconds);
});

it('should not accept mode=primary + tags', function () {
expect(() => new ReadPreference(PRIMARY, TAGS)).to.throw(
'Primary read preference cannot be combined with tags'
);
});

it('should not accept mode=primary + options.maxStalenessSeconds', function () {
expect(() => new ReadPreference(PRIMARY, null, { maxStalenessSeconds })).to.throw(
'Primary read preference cannot be combined with maxStalenessSeconds'
);
});

it('should accept (mode=secondary, tags=null, options)', function () {
const p2 = new ReadPreference(SECONDARY, null, { maxStalenessSeconds });
expect(p2).to.be.an.instanceOf(ReadPreference);
expect(p2.mode).to.equal(SECONDARY);
expect(p2.maxStalenessSeconds).to.equal(maxStalenessSeconds);
});

it('should accept (mode=secondary, tags, options)', function () {
const p3 = new ReadPreference(SECONDARY, TAGS, { maxStalenessSeconds });
expect(p3).to.be.an.instanceOf(ReadPreference);
expect(p3.mode).to.equal(SECONDARY);
expect(p3.tags).to.eql(TAGS);
expect(p3.maxStalenessSeconds).to.equal(maxStalenessSeconds);
});

it('should not accept (mode, options, tags)', function () {
expect(() => new ReadPreference(PRIMARY, { maxStalenessSeconds }, TAGS)).to.throw(
'ReadPreference tags must be an array'
);
});
});

it('Should correctly apply collection level read Preference to count', {
metadata: { requires: { mongodb: '>=2.6.0', topology: ['single', 'ssl'] } },

Expand Down
134 changes: 134 additions & 0 deletions test/unit/read_preference.test.ts
@@ -0,0 +1,134 @@
import { ReadPreference } from '../../src';
import { expect } from 'chai';

describe('class ReadPreference', function () {
const maxStalenessSeconds = 1234;
const { PRIMARY, SECONDARY, NEAREST } = ReadPreference;
const TAGS = [{ loc: 'dc' }];
describe('::constructor', function () {
it('should accept (mode)', function () {
expect(new ReadPreference(PRIMARY)).to.be.an.instanceOf(ReadPreference);
});

it('should accept valid (mode, tags)', function () {
expect(new ReadPreference(PRIMARY, [])).to.be.an.instanceOf(ReadPreference);
const p0 = new ReadPreference(NEAREST, TAGS);
expect(p0).to.have.property('mode', NEAREST);
});

it('should not accept invalid tags', function () {
expect(() => new ReadPreference(PRIMARY, 'invalid' as any)).to.throw(
'ReadPreference tags must be an array'
);
expect(
() => new ReadPreference(PRIMARY, { loc: 'dc' } as any, { maxStalenessSeconds })
).to.throw('ReadPreference tags must be an array');
});

it('should accept (mode, options)', function () {
const p1 = new ReadPreference(SECONDARY, { maxStalenessSeconds } as any);
expect(p1.mode).to.equal(SECONDARY);
expect(p1).to.have.property('maxStalenessSeconds', maxStalenessSeconds);
});

it('should not accept mode=primary + tags', function () {
expect(() => new ReadPreference(PRIMARY, TAGS)).to.throw(
'Primary read preference cannot be combined with tags'
);
});

it('should not accept mode=primary + options.maxStalenessSeconds', function () {
expect(() => new ReadPreference(PRIMARY, null, { maxStalenessSeconds })).to.throw(
'Primary read preference cannot be combined with maxStalenessSeconds'
);
});

it('should not accept mode=primary + options.hedge enabled', function () {
expect(() => new ReadPreference(PRIMARY, null, { hedge: { enabled: true } })).to.throw(
'Primary read preference cannot be combined with hedge'
);
});

it('should accept (mode=secondary, tags=null, options)', function () {
const p2 = new ReadPreference(SECONDARY, null, { maxStalenessSeconds });
expect(p2).to.be.an.instanceOf(ReadPreference);
expect(p2).to.have.property('mode', SECONDARY);
expect(p2).to.have.property('maxStalenessSeconds', maxStalenessSeconds);
});

it('should accept (mode=secondary, tags, options)', function () {
const p3 = new ReadPreference(SECONDARY, TAGS, { maxStalenessSeconds });
expect(p3).to.be.an.instanceOf(ReadPreference);
expect(p3).to.have.property('mode', SECONDARY);
expect(p3.tags).to.deep.equal(TAGS);
expect(p3).to.have.property('maxStalenessSeconds', maxStalenessSeconds);
});

it('should not accept (mode, options, tags)', function () {
expect(
() => new ReadPreference(PRIMARY, { maxStalenessSeconds } as any, TAGS as any)
).to.throw('ReadPreference tags must be an array');
});
});

describe('fromOptions factory method', () => {
it('should return undefined if no options are passed', () => {
const readPreference = ReadPreference.fromOptions();
expect(readPreference).to.be.undefined;
});

context('readPreference is string', () => {
it('should accept { readPreference }', function () {
const readPreference = ReadPreference.fromOptions({
readPreference: PRIMARY
});
expect(readPreference).to.be.an.instanceOf(ReadPreference);
expect(readPreference).to.have.property('mode', PRIMARY);
});

it('should accept { readPreference, readPreferenceTags }', function () {
const readPreference = ReadPreference.fromOptions({
readPreference: SECONDARY,
readPreferenceTags: TAGS
});
expect(readPreference).to.be.an.instanceOf(ReadPreference);
expect(readPreference).to.have.property('mode', SECONDARY);
expect(readPreference.tags).to.deep.equal(TAGS);
});

it('should accept { readPreference, maxStalenessSeconds }', function () {
const readPreference = ReadPreference.fromOptions({
readPreference: SECONDARY,
maxStalenessSeconds: maxStalenessSeconds
});
expect(readPreference).to.be.an.instanceOf(ReadPreference);
expect(readPreference).to.have.property('mode', SECONDARY);
expect(readPreference).to.have.property('maxStalenessSeconds', maxStalenessSeconds);
});

it('should accept { readPreference, hedge }', function () {
const readPreference = ReadPreference.fromOptions({
readPreference: SECONDARY,
hedge: {
enabled: true
}
});
expect(readPreference).to.be.an.instanceOf(ReadPreference);
expect(readPreference).to.have.property('mode', SECONDARY);
expect(readPreference.hedge).to.deep.equal({ enabled: true });
});
});

it('should not accept mode=primary + options.hedge', function () {
expect(() =>
ReadPreference.fromOptions({ readPreference: PRIMARY, hedge: { enabled: true } })
).to.throw('Primary read preference cannot be combined with hedge');
});

it('should not accept mode=primary + options.maxStalenessSeconds', function () {
expect(() =>
ReadPreference.fromOptions({ readPreference: PRIMARY, maxStalenessSeconds })
).to.throw('Primary read preference cannot be combined with maxStalenessSeconds');
});
});
});

0 comments on commit b9fbac5

Please sign in to comment.