Skip to content

Add option for connect timeout #726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 4, 2014
Merged

Add option for connect timeout #726

merged 1 commit into from
Feb 4, 2014

Conversation

dougwilson
Copy link
Member

This adds a new option connectTimeout which specifies a timeout (in milliseconds) for the initial connection to timeout. This applies to the time between sending data to the remote server and establishing a TCP connection. The default value is to not have a timeout, which makes it backwards-compatible.

This timeout is named connectTimeout because it specifically ONLY applies to the connection establishment, nothing else. This means that the timeout will no longer time out any operation after the connection has been successfully established.

Fixes #708
Fixes #717

@sidorares
Copy link
Member

lgtm 👍

@dresende
Copy link
Collaborator

dresende commented Feb 3, 2014

👍

@dougwilson
Copy link
Member Author

Hey guys, I do need to change one thing on this PR, though. Right now a timeout event will get emitted and sent down to a protocol error, but the socket itself will stay there still working on getting connected; I need to change it to destroy the socket when the timeout occurs still.


this._socket.setTimeout(this.config.connectTimeout, handleConnectTimeout);
this._socket.once('connect', function() {
this.setTimeout(0, handleConnectTimeout);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need to pass handler as argument here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed to remove the specific timeout listener. this.setTimeout(0, handleConnectTimeout); is the same as this.setTimeout(0); this.removeListener('timeout', handleConnectTimeout). The timeout listener needs to be removed so it does not trigger after we have established a connection, since this is just a timeout for connecting.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if block could also be written as:

if (this.config.connectTimeout) {
  var handleConnectTimeout = this._handleConnectTimeout.bind(this);

  this._socket.setTimeout(this.config.connectTimeout);
  this._socket.once('timeout', handleConnectTimeout);
  this._socket.once('connect', function() {
    this.setTimeout(0);
    this.removeListener('timeout', handleConnectTimeout);
  });
}

if that makes it clearer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just checked setTimeout(0) without handler and previous timer is not called

var net = require('net');
var s = net.connect(80, 'stackoverflow.com');
s.setTimeout(1000, function() { console.log('timeout');  });
s.on('connect', function() {
  console.log('connected!');
  s.setTimeout(0);
});

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, because when you run a.setTimeout(0) the socket will never emit a timeout event any more, because the timeout timers are unenrolled. But if some user-land code is setting a timeout on our socket, our timeout listener will then suddenly trigger. We need to remove our listener to be safe. Try:

var net = require('net');
var s = net.connect(80, 'stackoverflow.com');
s.setTimeout(1000, function() { console.log('timeout');  });
s.on('connect', function() {
  console.log('connected!');
  s.setTimeout(0);
  setTimeout(function(){
    // Sometime later some user code does
    s.setTimeout(2);
    // Which didn't do anything before, or maybe they are adding their own
    // timeout listener for some reason
    // Our timeout listener is now triggered since we never removed it
  },100);
});

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am just trying to make sure that this timeout function is only triggered for a timeout during the connection establishment and not at any possible later point, which is why I went through extra effort to remove the timeout listener we added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point

@sidorares
Copy link
Member

@dougwilson could you add a line to changelog as well please?

@dougwilson
Copy link
Member Author

@sidorares done :)

@sidorares
Copy link
Member

Interesting, domains test fail on node 0.8

 AssertionError: "TypeError: Cannot call method 'release' of undefined" == "Error: inside domain 3"
      at Domain.d1.run.d4.on.err4 (/home/travis/build/felixge/node-mysql/test/integration/connection/test-domains.js:68:12)
      at Domain.EventEmitter.emit (events.js:96:17)
      at process.uncaughtHandler (domain.js:61:20)
      at process.EventEmitter.emit (events.js:126:20)

@dougwilson
Copy link
Member Author

I re-ran the tests on Travis and it passed now. That test is flawed, because it does not check err from pool.getConnection in d3, so it is hard to know what the real error was. It was likely some error from the Travis CI MySQL, was was transient, as they passed this time without changing anything.

@sidorares
Copy link
Member

Great, merging

sidorares added a commit that referenced this pull request Feb 4, 2014
@sidorares sidorares merged commit 1dc38bc into mysqljs:master Feb 4, 2014
@dougwilson
Copy link
Member Author

@sidorares I also just sent PR #728 to re-throw those errors so if an error occurs at points in the domains test, we can see what happened on Travis CI.

@felixge
Copy link
Collaborator

felixge commented Feb 4, 2014

💖 thx for all the PRs @dougwilson !

@felixge
Copy link
Collaborator

felixge commented Feb 4, 2014

@dougwilson also just gave you commit bits / npm push access. Enjoy!

@dougwilson
Copy link
Member Author

Thanks, @felixge It shall not be abused!

@dougwilson dougwilson deleted the feature/connect-timeout branch February 4, 2014 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Throw error on connection failed in pool
4 participants