Improve client reconnect behavior
A client configured to reconnect should do so on socket close unless unbind was called explicitly. This covers cases where the connection undergoes clean but unexpected termination.
This commit is contained in:
parent
3edf9de578
commit
c7cd5da208
|
@ -678,6 +678,10 @@ Client.prototype.unbind = function unbind(callback) {
|
||||||
if (typeof (callback) !== 'function')
|
if (typeof (callback) !== 'function')
|
||||||
throw new TypeError('callback must be a function');
|
throw new TypeError('callback must be a function');
|
||||||
|
|
||||||
|
// When the socket closes, it is useful to know whether it was due to a
|
||||||
|
// user-initiated unbind or something else.
|
||||||
|
this.unbound = true;
|
||||||
|
|
||||||
if (!this.socket)
|
if (!this.socket)
|
||||||
return callback();
|
return callback();
|
||||||
|
|
||||||
|
@ -1023,9 +1027,13 @@ Client.prototype._onClose = function _onClose(had_err) {
|
||||||
});
|
});
|
||||||
delete socket.ldap.parser;
|
delete socket.ldap.parser;
|
||||||
delete socket.ldap;
|
delete socket.ldap;
|
||||||
if (had_err && this.reconnect) {
|
|
||||||
|
// Automatically fire reconnect logic if the socket was closed for any reason
|
||||||
|
// other than a user-initiated unbind.
|
||||||
|
if (this.reconnect && !this.unbound) {
|
||||||
this._connect();
|
this._connect();
|
||||||
}
|
}
|
||||||
|
this.unbound = false;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,14 @@ var SOCKET = '/tmp/.' + uuid();
|
||||||
|
|
||||||
var SUFFIX = 'dc=test';
|
var SUFFIX = 'dc=test';
|
||||||
|
|
||||||
|
var LOG = new Logger({
|
||||||
|
name: 'ldapjs_unit_test',
|
||||||
|
stream: process.stderr,
|
||||||
|
level: (process.env.LOG_LEVEL || 'info'),
|
||||||
|
serializers: Logger.stdSerializers,
|
||||||
|
src: true
|
||||||
|
});
|
||||||
|
|
||||||
var ldap;
|
var ldap;
|
||||||
var Attribute;
|
var Attribute;
|
||||||
var Change;
|
var Change;
|
||||||
|
@ -148,13 +156,7 @@ test('setup', function (t) {
|
||||||
client = ldap.createClient({
|
client = ldap.createClient({
|
||||||
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
||||||
socketPath: SOCKET,
|
socketPath: SOCKET,
|
||||||
log: new Logger({
|
log: LOG
|
||||||
name: 'ldapjs_unit_test',
|
|
||||||
stream: process.stderr,
|
|
||||||
level: (process.env.LOG_LEVEL || 'info'),
|
|
||||||
serializers: Logger.stdSerializers,
|
|
||||||
src: true
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
t.ok(client);
|
t.ok(client);
|
||||||
t.end();
|
t.end();
|
||||||
|
@ -622,13 +624,7 @@ test('setup action', function (t) {
|
||||||
var setupClient = ldap.createClient({
|
var setupClient = ldap.createClient({
|
||||||
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
||||||
socketPath: SOCKET,
|
socketPath: SOCKET,
|
||||||
log: new Logger({
|
log: LOG
|
||||||
name: 'ldapjs_unit_test',
|
|
||||||
stream: process.stderr,
|
|
||||||
level: (process.env.LOG_LEVEL || 'info'),
|
|
||||||
serializers: Logger.stdSerializers,
|
|
||||||
src: true
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
setupClient.on('setup', function (clt, cb) {
|
setupClient.on('setup', function (clt, cb) {
|
||||||
clt.bind(BIND_DN, BIND_PW, function (err, res) {
|
clt.bind(BIND_DN, BIND_PW, function (err, res) {
|
||||||
|
@ -652,13 +648,7 @@ test('setup reconnect', function (t) {
|
||||||
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
||||||
socketPath: SOCKET,
|
socketPath: SOCKET,
|
||||||
reconnect: true,
|
reconnect: true,
|
||||||
log: new Logger({
|
log: LOG
|
||||||
name: 'ldapjs_unit_test',
|
|
||||||
stream: process.stderr,
|
|
||||||
level: (process.env.LOG_LEVEL || 'info'),
|
|
||||||
serializers: Logger.stdSerializers,
|
|
||||||
src: true
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
rClient.on('setup', function (clt, cb) {
|
rClient.on('setup', function (clt, cb) {
|
||||||
clt.bind(BIND_DN, BIND_PW, function (err, res) {
|
clt.bind(BIND_DN, BIND_PW, function (err, res) {
|
||||||
|
@ -715,13 +705,7 @@ test('setup abort', function (t) {
|
||||||
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
||||||
socketPath: SOCKET,
|
socketPath: SOCKET,
|
||||||
reconnect: true,
|
reconnect: true,
|
||||||
log: new Logger({
|
log: LOG
|
||||||
name: 'ldapjs_unit_test',
|
|
||||||
stream: process.stderr,
|
|
||||||
level: (process.env.LOG_LEVEL || 'info'),
|
|
||||||
serializers: Logger.stdSerializers,
|
|
||||||
src: true
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
var message = 'It\'s a trap!';
|
var message = 'It\'s a trap!';
|
||||||
setupClient.on('setup', function (clt, cb) {
|
setupClient.on('setup', function (clt, cb) {
|
||||||
|
@ -743,13 +727,7 @@ test('abort reconnect', function (t) {
|
||||||
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT || 0, 10),
|
||||||
socketPath: '/dev/null',
|
socketPath: '/dev/null',
|
||||||
reconnect: true,
|
reconnect: true,
|
||||||
log: new Logger({
|
log: LOG
|
||||||
name: 'ldapjs_unit_test',
|
|
||||||
stream: process.stderr,
|
|
||||||
level: (process.env.LOG_LEVEL || 'info'),
|
|
||||||
serializers: Logger.stdSerializers,
|
|
||||||
src: true
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
var retryCount = 0;
|
var retryCount = 0;
|
||||||
abortClient.on('connectError', function () {
|
abortClient.on('connectError', function () {
|
||||||
|
@ -777,13 +755,7 @@ test('reconnect max retries', function (t) {
|
||||||
initialDelay: 10,
|
initialDelay: 10,
|
||||||
maxDelay: 100
|
maxDelay: 100
|
||||||
},
|
},
|
||||||
log: new Logger({
|
log: LOG
|
||||||
name: 'ldapjs_unit_test',
|
|
||||||
stream: process.stderr,
|
|
||||||
level: (process.env.LOG_LEVEL || 'info'),
|
|
||||||
serializers: Logger.stdSerializers,
|
|
||||||
src: true
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
var count = 0;
|
var count = 0;
|
||||||
rClient.on('connectError', function () {
|
rClient.on('connectError', function () {
|
||||||
|
@ -797,6 +769,63 @@ test('reconnect max retries', function (t) {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('reconnect on server close', function (t) {
|
||||||
|
var clt = ldap.createClient({
|
||||||
|
socketPath: SOCKET,
|
||||||
|
reconnect: true,
|
||||||
|
log: LOG
|
||||||
|
});
|
||||||
|
clt.on('setup', function (sclt, cb) {
|
||||||
|
sclt.bind(BIND_DN, BIND_PW, function (err, res) {
|
||||||
|
t.ifError(err);
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
clt.once('connect', function () {
|
||||||
|
t.ok(clt.socket);
|
||||||
|
clt.once('connect', function () {
|
||||||
|
t.ok(true, 'successful reconnect');
|
||||||
|
clt.destroy();
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Simulate server-side close
|
||||||
|
clt.socket.destroy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test('no auto-reconnect on unbind', function (t) {
|
||||||
|
var clt = ldap.createClient({
|
||||||
|
socketPath: SOCKET,
|
||||||
|
reconnect: true,
|
||||||
|
log: LOG
|
||||||
|
});
|
||||||
|
clt.on('setup', function (sclt, cb) {
|
||||||
|
sclt.bind(BIND_DN, BIND_PW, function (err, res) {
|
||||||
|
t.ifError(err);
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
clt.once('connect', function () {
|
||||||
|
clt.once('connect', function () {
|
||||||
|
t.ifError(new Error('client should not reconnect'));
|
||||||
|
});
|
||||||
|
clt.once('close', function () {
|
||||||
|
t.ok(true, 'initial close');
|
||||||
|
setImmediate(function () {
|
||||||
|
t.ok(!clt.connected, 'should not be connected');
|
||||||
|
t.ok(!clt.connecting, 'should not be connecting');
|
||||||
|
clt.destroy();
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
clt.unbind();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
test('abandon (GH-27)', function (t) {
|
test('abandon (GH-27)', function (t) {
|
||||||
client.abandon(401876543, function (err) {
|
client.abandon(401876543, function (err) {
|
||||||
t.ifError(err);
|
t.ifError(err);
|
||||||
|
|
|
@ -119,6 +119,7 @@
|
||||||
+define process
|
+define process
|
||||||
+define require
|
+define require
|
||||||
+define setInterval
|
+define setInterval
|
||||||
|
+define setImmediate
|
||||||
+define setTimeout
|
+define setTimeout
|
||||||
+define Buffer
|
+define Buffer
|
||||||
+define JSON
|
+define JSON
|
||||||
|
|
Loading…
Reference in New Issue