Skip to content
This repository has been archived by the owner on Feb 4, 2022. It is now read-only.

Commit

Permalink
fix(secondaries): fixes connection with secondary readPreference (#258)
Browse files Browse the repository at this point in the history
Ensures that when readPreference is `secondary`, the `connect`
event is not triggered until connection has been established
with a secondary.

Fixes NODE-1089
  • Loading branch information
daprahamian authored Dec 19, 2017
1 parent ec2b7a6 commit 0060ad7
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 4 deletions.
21 changes: 17 additions & 4 deletions lib/topologies/replset.js
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,22 @@ function applyAuthenticationContexts(self, server, callback) {
applyAuth(authContexts, server, callback);
}

function shouldTriggerConnect(self) {
const isConnecting = self.state === CONNECTING;
const hasPrimary = self.s.replicaSetState.hasPrimary();
const hasSecondary = self.s.replicaSetState.hasSecondary();
const secondaryOnlyConnectionAllowed = self.s.options.secondaryOnlyConnectionAllowed;
const readPreferenceSecondary =
self.s.connectOptions.readPreference &&
self.s.connectOptions.readPreference.equals(ReadPreference.secondary);

return (
(isConnecting &&
((readPreferenceSecondary && hasSecondary) || (!readPreferenceSecondary && hasPrimary))) ||
(hasSecondary && secondaryOnlyConnectionAllowed)
);
}

function handleInitialConnectEvent(self, event) {
return function() {
var _this = this;
Expand Down Expand Up @@ -835,10 +851,7 @@ function handleInitialConnectEvent(self, event) {
_this.on('parseError', handleEvent(self, 'parseError'));

// Do we have a primary or primaryAndSecondary
if (
(self.state === CONNECTING && self.s.replicaSetState.hasPrimary()) ||
(self.s.replicaSetState.hasSecondary() && self.s.options.secondaryOnlyConnectionAllowed)
) {
if (shouldTriggerConnect(self)) {
// We are connected
self.state = CONNECTED;

Expand Down
51 changes: 51 additions & 0 deletions test/tests/unit/replset/read_preference_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';

const expect = require('chai').expect;
const ReplSet = require('../../../../lib/topologies/replset');
const ReadPreference = require('../../../../lib/topologies/read_preference');
const mock = require('../../../mock');
const ReplSetFixture = require('../common').ReplSetFixture;

describe('Secondaries (ReplSet)', function() {
let test;
before(() => (test = new ReplSetFixture()));
afterEach(() => mock.cleanup());
beforeEach(() => test.setup());

it('Should not be "connected" with ReadPreference secondary unless secondary is connected', {
metadata: {
requires: {
topology: 'single'
}
},

test: function(done) {
const replSet = new ReplSet(
[test.primaryServer.address(), test.firstSecondaryServer.address()],
{
setName: 'rs',
connectionTimeout: 3000,
socketTimeout: 0,
haInterval: 100,
size: 1
}
);

replSet.on('error', done);

replSet.on('connect', server => {
let err;
try {
expect(server.s.replicaSetState.hasSecondary()).to.equal(true);
} catch (e) {
err = e;
}

replSet.destroy();
done(err);
});

replSet.connect({ readPreference: new ReadPreference('secondary') });
}
});
});

0 comments on commit 0060ad7

Please sign in to comment.