-
Notifications
You must be signed in to change notification settings - Fork 64
Conversation
calebboyd
left a comment
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.
Neat! I'm excited to see that the pool is being dropped.
I did notice that promise support is still a bit second class. In that -- promisified apis would be able to perform much better than the scheme currently used.
index.js
Outdated
| this.emit('error', e, client) | ||
| }.bind(this)) | ||
| function release (client, err) { | ||
| client.release = function () { throw new Error('called release twice') } |
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 function could be hoisted
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.
good call. done.
index.js
Outdated
| this._pulseQueue() | ||
| } | ||
|
|
||
| Pool.prototype.connect = function (cb) { |
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.
It looks like the callback in the new version may be unintentionally synchronous where the old version was async
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.
Is that bad? It's a semver major bump & I'd rather not introduce a nextTick just to keep it async.
|
|
||
| const describe = require('mocha').describe | ||
| const it = require('mocha').it | ||
| const BluebirdPromise = require('bluebird') |
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.
BluebirdPromise.coroutine == co.wrap if you want to drop a dep
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.
nice! today I learned!
index.js
Outdated
| reject(err) | ||
| } | ||
| return | ||
| return cb(err, undefined, function () { }) |
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.
I think this block is unreachable based on the use of _pendingQueue
index.js
Outdated
| this.log('ending') | ||
| if (this.ending) { | ||
| const err = new Error('Called end on pool more than once') | ||
| return cb ? cb(err) : this.Promise.reject(err) |
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.
sync : async
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.
Is it bad to do sync if its a callback and async if it's a promise? Promises are always async, but callbacks done necessarily have to be and AFAIK there's never been an idiom saying they should be.
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.
In general, Its not good to mix async and sync in the same API. Whats weird here is nothing invoked internally is actually async except the result. In one case I can get the error synchronously (looks async) and the other, async.
If I were to express a preference it would be to stick with an async api throughout.
Here is a tree of posts that go into a lot more detail http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony
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.
Good point - I'll fix this
index.js
Outdated
| return promised.result | ||
| } | ||
|
|
||
| Object.defineProperty(Pool.prototype, 'waitingCount', { |
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.
Could clean this up a lot if the export was switched to something like:
module.exports = function (options, client) {
return new PgPool(options, client)
}
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.
I'm not following how this would be cleaned up? Could you expand on what you meant here?
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.
np, I just mean taking advantage of the class sugar for function defs and getters of the new min node version =)
class PgPool {
_isFull() {..}
...
connect() {...}
...
get waitingCount() {...}
get totalCount() {...}
get idleCount() {...}
}
module.exports = function (options, client) {
return new PgPool(options, client)
}
```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.
I'll try that & see if it works in node 4. If so, definitely will go this way.
index.js
Outdated
| const response = this._promisify(cb) | ||
| const result = response.result | ||
| cb = response.callback | ||
| this._pendingQueue.push((err, client) => { |
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.
proposal: instead of handling this in a closure -- just store the waiter and handle this when invoking it during dequeue/shift
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.
excellent suggestion! cleaned this up.
| - node_js: "6" | ||
| addons: | ||
| postgresql: "9.4" | ||
| - node_js: "8" |
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.
Just wonder : why remove node 8 ?
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.
it was messing up in travis but working locally even though the same tests were passing locally - I just removed it temporarily so I could make sure the other tests were passing. I'll need to get it working in travis eventually.
|
Thank you so much for the feedback and review! I'm not quite done w/ this branch yet - code's still a bit dirty...but have quite a bit of client work in the next few days so I'll take me a bit of time to get to this. But know I'm grateful & I'll be back within a day or two! 💃 |
@calebboyd - using callbacks internally in this module is so we can support |
|
Mostly I think that it would be best to stick with one API or the other. For example, In general sticking with callbacks here will allow people who use promises (I'm one) to do so with the lowest overhead, which is a plus for the library that proxies queries. |
|
I guess that wasn't super clear. I don't have anything that would stop me from using this (I could promisify it anyways to avoid the issue). But Maybe the removal of |
|
I'll take a look at hard look at the code once I finish it to ensure it's not doing unnecessary work wrt allocating promises. It should only allocate a promise if you don't supply a callback: if you use a callback it will never even allocate any promises so you don't have to be concerned about any performance as some folks who use callbacks tend to be. 🙅 As far as The goal is to support both promises and callbacks in a transparent way versus requiring someone run Thanks again for the feedback & comments. They're very helpful! 👏 |
|
Thank you for entertaining them. I'm very grateful for your work on these tools 🔨 |
This contains a massive number of internal changes. However, the external API remains very close to the same.
The breaking changes are:
maxandidleTimeoutMillisnewkeywordI attempted to upgrade to node-pool@3.x, but it weirdly no longer supports returning an error when a client fails to connect. Instead it tries to reconnect the client in a tight loop and makes the error non-actionable. I was unable to find a good way to hook into this behavior and override it. Furthermore it has a lot of additional bells and whistles for priority queuing, min levels, auto-connection, and other behavior pg and pg-pool have never used. Initially I was distraught at the thought of implementing the pooling behavior here, but it turns out it wasn't very much code & all the tests still pass!
After this I spent some time going through and writing tests for many of the open issues to verify they no longer happen. I also added support for the long requested
connectionTimeoutMillis- now supplyingconnectionTimeoutMillisas a millisecond value will cause the pool to return an error on yourconnectcall if a connection could not be established within the configured time. By default there is no timeout.Known fixes:
pg>=5.0is apeerDependency. closes pg dependency #45.endingproperty which will allow you to inspect when the pool is in the process of shutting down. closes Fails to reconnect after invoking end() #58idleTimeoutMillisof 0 disables idle timeout. closes Does idleTimeoutMillis = -1 keep connections open indefinently #64