question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

RFC Allow repeat calls to `connect()` to resolve

See original GitHub issue

It seems that there is a common use where developers would like to call ConnectionPool.connect() repeatedly to then chain on a request.

For example:

const pool = new ConnectionPool();

function runQuery(query) {
   return pool.connect().then(connectedPool => {
        return connectedPool.request().query('SELECT 1');
    });
}

At the moment, repeat calls to connect() in the above example will throw an error because the pool is already connected.

This also has the advantage of allowing developers not to have to worry about whether the pool is connected or closed. At the moment, to achieve something similar you’d need to do the following:

const pool = new ConnectionPool();

function runQuery(query) {
    return Promise.resolve(pool.connected ? pool : pool.connect()).then(connectedPool => {
        return connectedPool.request().query('SELECT 1');
    });
}

This feels overly verbose and needless and should be simple to solve.

As an enhancement, we may wish to do something similar for when the pool is in a “connecting” state. At the moment if two process call connect() whilst the pool is connecting, we will see an error, which will mean that using the pool.connect().then() pattern will be inherently unsafe for any parallel execution of queries on a pool that’s not yet connected.

It feels like we are relying on devs to do too much caretaking of the pool when the library should be able to abstract that away.

Potentially the final solution could just be a lazily invoked connection. eg:

const pool = new ConnectionPool();

function runQuery(query) {
    // internally it will check if the pool has connected, if not it will attempt to connect and then run the query
    return pool.request().query(query);
}

developers can still call connect() to validate the connection is working but they wouldn’t need to worry about the connected or connecting state of the pool at all.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:4
  • Comments:12

github_iconTop GitHub Comments

2reactions
brokenthorncommented, Nov 13, 2019

Shouldn’t the docs and examples also be updated?

1reaction
brokenthorncommented, Nov 13, 2019

Here’s the other solution I was talking about. This one I actually tested.

I’m using Typescript because the example is from a project of mine. It’s not part of a runQuery function but a get a pool that’s actually connected before trying to run a query function.

let millisecondsPassed = 0;
// Basically let's write a recursive executor with a timeout
// and 'passed time' threshold so it doesn't recurse forever:
const waitForConnectionPoolToBeReadyExecutor = (
  resolve: (value?: PromiseLike<undefined> | undefined) => void,
  reject: (reason?: any) => void,
) => {
  setTimeout(() => {
    if (millisecondsPassed < 30000) {
      millisecondsPassed += 2000;

      // This variable defaults to false and is asynchronously set by the
      // pool init callback set on the pool constructor:
      // ie.: new(options, callback) where if not error, this._connectionPoolInitialized = true.
      //
      // Could as well be replaced with `this._connectionPool.connected`.
      if (this._connectionPoolInitialized) {
        resolve();
      } else {
        waitForConnectionPoolToBeReadyExecutor(resolve, reject);
      }
    } else
      reject(
        "Aborting start because the connection pool failed to initialize in the last ~30s.",
      );
  }, 2000);
};

// This simply now waits for like 30 seconds, for the pool to become connected.
// Since this is also an async function, if this fails after 30 seconds, execution stops
// and an error is thrown.
await new Promise(waitForConnectionPoolToBeReadyExecutor);

// use the pool: await this._connectionPool.request().query()... etc.
Read more comments on GitHub >

github_iconTop Results From Across the Web

RFC 3261: SIP: Session Initiation Protocol
1 Adding Bindings The REGISTER request sent to a registrar includes the contact address(es) to which SIP requests for the address-of-record should be...
Read more >
SIP: Session Initiation Protocol (RFC 2543) - IETF
The REGISTER request allows a client to let a proxy or redirect server know at which address(es) it can be reached. A client...
Read more >
HTTP/1.1: Connections
- HTTP requests and responses can be pipelined on a connection. Pipelining allows a client to make multiple requests without waiting for each...
Read more >
Hypertext Transfer Protocol - Wikipedia
The Hypertext Transfer Protocol (HTTP) is an application layer protocol in the Internet ... Development of early HTTP Requests for Comments (RFCs) started...
Read more >
429 Too Many Requests - HTTP - MDN Web Docs
The HTTP 429 Too Many Requests response status code indicates the user has sent too many requests in a given amount of time...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found