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

Allow repeat calls to ConnectionPool.connect() #941

Merged
merged 12 commits into from
Feb 10, 2020

Conversation

dhensby
Copy link
Collaborator

@dhensby dhensby commented Nov 13, 2019

Depends on #940

closes #934

This PR implements the feature proposal outlined in #934 - it allows developers to make repeat calls to the ConnectionPool.connect() function (and have them resolve as appropriate) even if the pool is in a connected or connecting state.

This has been achieved by:

  1. Immediately resolving callbacks if the pool is in a connected state
  2. Stacking connect callbacks so that they can be resolved in parallel once the connection promise has resolved

This does not touch on the further enhancements in #934, namely there is no auto-connect feature added, as this feels a lot more risky and the behaviour under certain edge-cases is harder to define.

todo:

  • Docs

@dhensby dhensby force-pushed the pulls/repeat-connect-calls branch 5 times, most recently from 10d4010 to a2222bf Compare November 15, 2019 13:21
@dhensby
Copy link
Collaborator Author

dhensby commented Nov 16, 2019

Last thing to consider is what to do if a ConnectionPool is closing and a connect call is made. Should connect throw, or should it just queue up a new connection?

If users start running code like pool.connect().then(() => pool.query()).then(() => pool.close()) in parallel, we will be able to handle it, but it will be an absolutely terrible way to use the library because it will be creating and destroying pools all the time including running the probe connection before connect() resolves.

For now, I've allowed this usage, but maybe we should throw an error?

@dhensby dhensby marked this pull request as ready for review November 16, 2019 14:02
lib/base/connection-pool.js Outdated Show resolved Hide resolved
lib/base/connection-pool.js Outdated Show resolved Hide resolved
lib/base/connection-pool.js Outdated Show resolved Hide resolved
test/common/tests.js Outdated Show resolved Hide resolved
test/msnodesqlv8/msnodesqlv8.js Outdated Show resolved Hide resolved
test/tedious/tedious.js Outdated Show resolved Hide resolved
lib/base/connection-pool.js Outdated Show resolved Hide resolved
@dhensby
Copy link
Collaborator Author

dhensby commented Nov 17, 2019

Perhaps I can add some more thorough tests to how the base pool handles connecting / closing of the pool

@dhensby
Copy link
Collaborator Author

dhensby commented Nov 18, 2019

I'm starting to stumble upon some of the issues with allowing repeat calls to connect especially if it means we start to allow / encourage free usage of pool.connect().then(() => pool.request().query()).then(() => pool.close()) - because this means there's no longer a guarantee that the pool will be connected once the connected call resolves. That is because the close call can execute after a connection and query has run but not after all queries have run (and we will never know this).

Here's a failing case:

const pool = new sql.ConnectionPool(config)
      Promise.all([
        pool.connect().then(() => pool.request().query('SELECT 1')).then(() => pool.close()),
        pool.connect()
          .then(() => pool.request().query('SELECT 2'))
          // here the pool has been closed
          .then(() => pool.request().query('SELECT 3'))
          .then(() => pool.close()),
      ]).then(() => {
        done()
      }).catch(done)

My expectation is that we don't encourage this use of connect and close, but it is something people might be tempted to do and could lead to connect resolving a pool that isn't connected under some circumstances. Perhaps this is just an edge case to be aware of, because I still think it's best that connect resolves even if the pool is already connected.

An alternative would be that if close is called whilst connect is executing, we could actually reject all the connection promises so they can't resolve and instead error... In that instance the above then calls after the connect would never resolve

@willmorgan
Copy link
Collaborator

My expectation is that we don't encourage this use of connect and close, but it is something people might be tempted to do and could lead to connect resolving a pool that isn't connected under some circumstances. Perhaps this is just an edge case to be aware of, because I still think it's best that connect resolves even if the pool is already connected.

I think a better way for these kinds of cases is to start by questioning why they're using a pool to begin with, if they're doing what would appear to be one-off operations which imply only a single connection is going to be used. In that case only a single connection should be required and pooling is overkill.

@brokenthorn
Copy link

brokenthorn commented Nov 21, 2019 via email

@dhensby
Copy link
Collaborator Author

dhensby commented Jan 3, 2020

I mean, you can argue that repeatedly calling connect is bad code design too!

I might spend a bit more time looking into this, though...

willmorgan
willmorgan previously approved these changes Feb 5, 2020
@dhensby dhensby merged commit e7560dc into tediousjs:master Feb 10, 2020
@dhensby dhensby deleted the pulls/repeat-connect-calls branch February 10, 2020 09:22
@ghost

This comment has been minimized.

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.

RFC Allow repeat calls to connect() to resolve
3 participants