Skip to content

Commit 23d6777

Browse files
authored
Merge pull request #172 from IanMcCurdy/tcpkeepalive
Add configurable TCP keepalive
2 parents 4ae917b + 0e298c8 commit 23d6777

5 files changed

Lines changed: 125 additions & 2 deletions

File tree

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Table of contents
2323
* [Transaction handling](#transaction-handling)
2424
* [Streaming Large Objects](#streaming-large-objects)
2525
* [CESU-8 encoding support](#cesu-8-encoding-support)
26+
* [TCP Keepalive](#tcp-keepalive)
2627
* [Running tests](#running-tests)
2728
* [Running examples](#running-examples)
2829

@@ -586,6 +587,38 @@ This setting is per client and cannot be changed later.
586587

587588
__Note:__ Using CESU-8 brings performance penalties proportionate to the text size that has to be converted.
588589

590+
TCP Keepalive
591+
-------------
592+
593+
To configure TCP keepalive behaviour, include the tcpKeepAliveIdle connect option. The value provided for this option is the number of seconds before an idle connection will begin sending keepalive packets. By default, TCP keepalive will be turned on with a value of 200 seconds. If a value of 0 is specified, keepalive behaviour is determined by the operating system.
594+
The following example creates a client whose connections will begin sending keepalive packets after 300 seconds.
595+
596+
```js
597+
var hdb = require('hdb');
598+
var client = hdb.createClient({
599+
host : 'hostname',
600+
port : 30015,
601+
user : 'user',
602+
password : 'secret',
603+
tcpKeepAliveIdle : 300
604+
});
605+
606+
```
607+
608+
TCP keepalive can be explicity disabled by specifying tcpKeepAliveIdle=false as in the example below.
609+
610+
```js
611+
var hdb = require('hdb');
612+
var client = hdb.createClient({
613+
host : 'hostname',
614+
port : 30015,
615+
user : 'user',
616+
password : 'secret',
617+
tcpKeepAliveIdle : false
618+
});
619+
620+
```
621+
589622
Running tests
590623
-------------
591624

lib/protocol/tcp.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
var net = require('net');
1717
var tls = require('tls');
18+
var defaultKeepAliveIdle = 200000; // milliseconds
1819

1920
exports.createSocket = net.connect;
2021
exports.createSecureSocket = tls.connect;
@@ -32,5 +33,17 @@ exports.connect = function connect(options, cb) {
3233
}
3334
var socket = createSocket(options, cb);
3435
socket.setNoDelay(true);
36+
var keepAliveIdle = defaultKeepAliveIdle;
37+
var enableKeepAlive = true;
38+
if ('tcpKeepAliveIdle' in options) {
39+
var val = options['tcpKeepAliveIdle'];
40+
if (val === false) {
41+
enableKeepAlive = false;
42+
} else {
43+
keepAliveIdle = val * 1000;
44+
if (isNaN(keepAliveIdle)) keepAliveIdle = defaultKeepAliveIdle;
45+
}
46+
}
47+
socket.setKeepAlive(enableKeepAlive, keepAliveIdle);
3548
return socket;
3649
};

test/hdb.Client.js

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,71 @@ describe('hdb', function () {
227227

228228
});
229229

230+
describe('#TCP keepalive', function () {
231+
232+
var tcp = require('../lib/protocol/tcp');
233+
var originalCreateSocket = tcp.createSocket;
234+
var socketStub;
235+
236+
beforeEach(function () {
237+
socketStub = new mock.createSocket({});
238+
socketStub.setNoDelay = function () {
239+
process.nextTick(function () {
240+
socketStub.write();
241+
});
242+
};
243+
tcp.createSocket = function () {
244+
return socketStub;
245+
};
246+
});
247+
248+
afterEach(function () {
249+
tcp.createSocket = originalCreateSocket;
250+
});
251+
252+
it('should set tcpKeepAliveIdle by default', function (done) {
253+
var client = new lib.Client({});
254+
client.connect(function (err) {
255+
should(client._connection._socket.keepAlive).be.true();
256+
should(client._connection._socket.keepAliveIdle).be.equal(200000);
257+
done();
258+
});
259+
});
260+
261+
it('should set tcpKeepAliveIdle via numeric connect option', function (done) {
262+
var client = new lib.Client({
263+
tcpKeepAliveIdle: 300
264+
});
265+
client.connect(function (err) {
266+
should(client._connection._socket.keepAlive).be.true();
267+
should(client._connection._socket.keepAliveIdle).be.equal(300000);
268+
done();
269+
});
270+
});
271+
272+
it('should set tcpKeepAliveIdle via string connect option', function (done) {
273+
var client = new lib.Client({
274+
tcpKeepAliveIdle: '300'
275+
});
276+
client.connect(function (err) {
277+
should(client._connection._socket.keepAlive).be.true();
278+
should(client._connection._socket.keepAliveIdle).be.equal(300000);
279+
done();
280+
});
281+
});
282+
283+
it('should disable tcp keepalive', function (done) {
284+
var client = new lib.Client({
285+
tcpKeepAliveIdle: false
286+
});
287+
client.connect(function (err) {
288+
should(client._connection._socket.keepAlive).be.false();
289+
done();
290+
});
291+
});
292+
293+
});
294+
230295
it('should connect with saml assertion', function (done) {
231296
var client = new TestClient({
232297
assertion: 'assertion'
@@ -804,4 +869,4 @@ describe('hdb', function () {
804869
});
805870

806871
});
807-
});
872+
});

test/lib.tcp.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ var createSecureSocket = tcp.createSecureSocket;
1919
var socket = {
2020
setNoDelay: function setNoDelay(noDelay) {
2121
noDelay.should.equal(true);
22-
}
22+
},
23+
setKeepAlive: function setKeepAlive(enable, time) {}
2324
};
2425

2526
describe('Lib', function () {

test/mock/MockSocket.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ function MockSocket(options) {
2525
this.writable = true;
2626
this.readable = true;
2727
this.delay = options.delay || 1;
28+
this.keepAlive = false;
29+
this.keepAliveIdle = 0;
2830
this.invalidInitializationReply = !!options.invalidInitializationReply;
2931
this.initializationErrorCode = options.initializationErrorCode;
3032
var chunk;
@@ -69,6 +71,15 @@ MockSocket.prototype.write = function write() {
6971
}, this.delay);
7072
};
7173

74+
MockSocket.prototype.setKeepAlive = function setKeepAlive(enable, time) {
75+
if (enable) {
76+
this.keepAlive = true;
77+
this.keepAliveIdle = time;
78+
} else {
79+
this.keepAlive = false;
80+
}
81+
};
82+
7283
Object.defineProperty(MockSocket.prototype, 'readyState', {
7384
get: function () {
7485
if (this.readable && this.writable) {

0 commit comments

Comments
 (0)