NATS#connect - specify socket timeout options [Feature Request]
See original GitHub issueIntroduction
The NATS.connect()
method, when given an unreachable IP address, times out after the default 120s (2 minutes). However, this time period is too long for constantly changing microservices and their respective upstream NATS transporters. There should be a way for a client to specify the timeout manually as a property to the options passed to the .connect()
method.
Rationale
In an environment where connection parameters are provided through a reactive KV store (etcd, Consul, etc.) the application should have the ability to know when a given Host/IP and port pair is unreachable in a specific amount of time lest incurring a downtime of no visibility for at least 2 minutes.
Consider a case where the configuration parameters have just been changed and the services are reloading; for 2 minutes, they will just hang with no output thus not giving any real telemetry data pointing to am erred configuration option.
Implementation
In order to understand the implementation, we must first look at the line which actually initializes a TCP connection:
https://github.com/nats-io/nats.js/blob/407193dbe851ac336da4c9cff1e052ffd9328bdf/lib/nats.js#L869
net.createConnection(port, host)
calls socket.connect(port, host)
wherein the default socket options (inter alia, timeout
set to 120000
) are used.
Caveat
The net
module does not provide a method to set the connect timeout; the socket.setTimeout
sets the time before which the socket is destroyed when no data is received or sent (basically it sets the SO_RCVTIMEO
and SO_SNDTIMEO
parameters).
Basic Implementation
We can abuse how .setTimeout()
works and wrap the connect method as a deferred function call.
Something like this, probably:
const net = require( 'net' );
const socket = net.createConnection( port, host );
const _timeout = setTimeout( () => {
socket.destroy();
throw new errors.SocketTimeoutError( options.timeout );
}, options.timeout );
socket.on( 'connect', () => clearTimeout( _timeout ) );
this.stream = socket;
The idea here is that if we do not receive the connect
event after options.timeout
milliseconds, the function in the setTimeout()
call will destroy the socket and throw an error which the client can use to understand what happened. If, however, the socket manages to connect within the specified period, we just clear the timeout thus preventing it from throwing any errors.
Please keep in mind that this is just a very basic PoC-like approach and might require some test cases to ensure cross-platform compatibility.
Conclusion
That is what I had in mind. I’d be more than happy to submit a PR for this should this feature be accepted. 😄
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (6 by maintainers)
Top GitHub Comments
@labsvisual - already have it ready 😃
@labsvisual I have published this new option, on the next release channel. To get it simply
npm install nats@next
.