-
Notifications
You must be signed in to change notification settings - Fork 259
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
Add option to error if the pool is full #125
Conversation
Hi there Kevin. I've currently got a half finished/started branch on my laptop that adds optional support for an acquire timeout, and allows for limiting the size of the waiting resource request list. The basic idea is that each call to |
I totally didn't see the actual code that came with this PR!!! So sorry, let me have a look and I'll get back to you. |
Thanks, @sandfox! |
Currently if you call pg.connect(), the call will block indefinitely until a connection becomes available. In many cases, if a connection is not available after some period of time, it's preferable to return an error (and call control) to the client, instead of tying up resources forever. Blocking on resource checkout also makes it easier for clients to deadlock - recently at Shyp, we had a situation where a row got locked and the thread that could unlock it was blocked waiting for a connection to become available, leading to deadlock. In that situation, it would be better to abort the checkout, which would have errored, but also broken the deadlock. Add two new settings to defaults: `block`, which, if false, will immediately return an error if the pool is full when you attempt to check out a new connection. Also adds `acquireTimeout`, which will wait for `acquireTimeout` milliseconds before giving up and returning an error. This builds on two pull requests against `generic-pool`: - Support options.block: coopernurse/node-pool#125 - Support options.timeout: coopernurse/node-pool#127 For the moment I'm pointing `generic-pool` at a branch that incorporates both of these commits. I'm marking this as a proof-of-concept until those go through, which hopefully they will soon. I'd also like feedback on the API. Adds semicolons in many places that omitted them and fixes several typos. I'm happy to pull those out into a different commit. Sets the TZ=GMT environment variable before running the tests; without this value set, and with a Postgres server set to the America/Los_Angeles timezone, a timezone test failed. Fixes brianc#782 and brianc#805. Will help alleviate brianc#902. May help with brianc#397.
if (this._draining) { | ||
throw new Error('pool is draining and cannot accept work') | ||
} | ||
if (options !== null && typeof options !== "undefined" && options.block === false && this._count >= this._factory.max) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be _total
, not _count
. My fault. I'll add a test for this fix it tomorrow PST.
4cb05b2
to
3d6d8ca
Compare
Ok - I think I pushed the right check - if I am reading correctly, |
Thanks for this @kevinburkeshyp. Having no timeout is troublesome at best. I was not looking forward at the prospect of having to do this. Hopefully the chain of PR's you've prepped will go through quickly (for the better good) |
@brianc proposed making these two options a single property: brianc/node-postgres#939 (comment) Also, I need to look at the test failure, there's likely a race somewhere. Previously I was running into an issue where timers on node v0.10.30 were firing 50ms early, but I don't think this failure is that. |
Currently, if you attempt to acquire a resource and the pool is full, the callback will not run until a space becomes available. This can lead to a deadlock if a pool member's release is blocked on the acquire callback running. To mitigate the deadlock possibility, support a third argument `pool.acquire(cb, priority, {block: false})`, which will immediately hit the callback with an error if the pool is full. Adds a test that this behaves as expected. Adds a helper function pool._isFull, which checks both the _count and the list of _availableObjects - I think we have to check both to ensure that the pool is full, and that this abstraction doesn't exist yet. Callers may want to wait for a small amount of time before giving up on the pool; I'm going to add that option in a second commit. This work was sponsored by [Shyp](https://shyp.com).
3d6d8ca
to
6d1dd23
Compare
Ok this looks pretty good with one small change needed: One line 395
this callback needs wrapping in a setImmediate/process.nextTick so that the callback is fired on the next cycle round the event loop so that it maintains because we support node 0.8 we'll need to use/do something like https://www.npmjs.com/package/setimmediate (I'd settle for something hacky in favour of another dependency which I want to avoid at all costs (a bundled dependency as long as $ANCIENT version of npm supports it would be an ok tradeoff) All that said.... I think I prefer the idea of making It's not pretttty, but Sorry again for taking a while to look at this! |
OK. Is
Fine by me. Should I squash these two PR's into one? Push here or open a new one? |
Closing this, since we decided not to add a |
Currently, if you attempt to acquire a resource and the pool is full, the
callback will not run until a space becomes available. This can lead to a
deadlock if a pool member's release is blocked on the acquire callback running.
To mitigate the deadlock possibility, support a third argument
pool.acquire(cb, priority, {block: false})
, which will immediately hit thecallback with an error if the pool is full. Adds a test that this behaves as
expected.
Callers may want to wait for a small amount of time before giving up on the
pool; I'm going to add that option in a second commit.
This work was sponsored by Shyp.