Skip to content
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

POC: Time out pg.connect() call #939

Closed
wants to merge 1 commit into from
Closed

Conversation

kevinburkeshyp
Copy link
Contributor

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:

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 #782 and #805. Will help alleviate #902. May help with #397.

pg.defaults.block = false;
pg.defaults.poolSize = 1;

test('pool#connect acquire errors if the pool is full', function() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

One of these tests introduces an unnecessarily long timeout, maybe 2 seconds. I'm not super familiar with how the test runner knows when tests are done or I would address it, was hoping you'd know :(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also - there are more tests around the generic-pool implementation then there are here, this just covers the common cases.

@@ -4,10 +4,10 @@ connectionString=postgres://

params := $(connectionString)

node-command := xargs -n 1 -I file node file $(params)
node-command := TZ=GMT xargs -n 1 -I file node file $(params)
Copy link
Owner

Choose a reason for hiding this comment

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

+1 nice - sorry I missed that one!

@brianc
Copy link
Owner

brianc commented Feb 19, 2016

I'm a big +1 on these features! Thanks for putting in the time to implement these. I'm on a cruise right now 🚢 with very very bad internet speeds so apologies for taking a while to get to this.

As far as the test runner is concerned its very primitive because node-postgres was written before most of the now standard test frameworks for node existed, so I rolled my own with makefiles. Timeouts are handled by the test suite hanging indefinitely - so you can use as short of timeouts as you want. Once I'm back on Monday I'll have time to finish reviewing this - there are a few utility methods I monkey-patched on to the assert module way back in the day that make testing async code easier...I'll try pointing them out once I get to a place where I can pull up new internet pages in under 30 seconds. :grimace:

@brianc
Copy link
Owner

brianc commented Feb 25, 2016

Hey @kevinburkeshyp thanks again for putting this together! Once the PR is merged for node-pool if you can, just update this PR to use the npm published version in package json, then come back here and @ mention me on this PR & I'll merge it up! 💃

@vitaly-t
Copy link
Contributor

I hope this is merged soon ;)

@brianc
Copy link
Owner

brianc commented Apr 28, 2016

Hey @kevinburkeshyp did the changes ever land upstream in generic pool allowing for a timeout before failing the connection?

@kevinburkeshyp
Copy link
Contributor Author

no, the maintainer has said for 3 months now he's going to look at it, but no progress

@brianc
Copy link
Owner

brianc commented Apr 28, 2016

Ah - sorry about that! That maintainer sounds about as slow as me. 😬 Once its on npm I'll merge this ASAP.

@vitaly-t
Copy link
Contributor

Can we not finish this without that maintainer? He may as well never come back at this point...

@brianc
Copy link
Owner

brianc commented Apr 28, 2016

If you fork generic-pool and push it to a new package on npm & then add that package as a dependency that will unblock this - I don't think that is the ideal solution, but it would work. This would also need to be cleaned up so it would once again cleanly merge into master. Then we're good to go! 👏

@kevinburkeshyp
Copy link
Contributor Author

Sounds good! Will let you know!

@kevinburke
Copy link
Contributor

Submitted as #1006! Closing.

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 a new setting to defaults: `acquireTimeout`, which will wait for
`acquireTimeout` milliseconds before giving up and returning an error. If the
value is undefined (the default), `node-postgres` will continue to wait
indefinitely for a connection to become available.

This builds on a pull request against `generic-pool`, support options.timeout:
coopernurse/node-pool#127. Review has been slow going,
so I published a new package with that change as `generic-pool-timeout`, and
updated the reference in this codebase.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

More documentation on pooling
5 participants