-
Notifications
You must be signed in to change notification settings - Fork 8
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
Pool2 acquisition failure causes resource to hang around #30
Comments
Yikes, that's a pretty bad oversight on my part. Given you're dealing with streams, it's probably fine to return the stream as acquired immediately, so that there is something to be passed along to the dispose function which can clean it up properly. Streams can accept writes before they are open, generally. I think we can take a cue from FRP style programming here and allow you to return a function from the acquire callback, which function will handle disposing of/destroying the resource as cleanly as possible. Would that suit you? Essentially, you would, at the end of your acquire function, do something like this: acquire: (cb: (err: any, res?: tls.ClearTextStream) => void) => {
let stream = tls.connect(opts);
stream.once('secureConnect', () => {
cb.removeAllListeners();
cb(null, stream);
});
stream.once('error', (err: Error) => {
cb(err);
});
return () => stream.destroy();
} I could then call it on timeouts, and maybe later down the line this can be used as a more general dispose approach, eliminating the separate disposer property. Does that meet your need? |
That would work great. Thanks. On Thu, Nov 10, 2016, 19:44 Kris Reeves notifications@github.com wrote:
|
I just published a version 1.4, give it a try and let me know. Sorry it took so long, I had just left on vacation! |
...you know, it occurs to me that I got this all wrong. This was intentional, if maybe unclear, behavior. The idea was that even if THIS acquire times out, the resource will still be in the pool (as long as it doesn't fail) to serve the next request(s). I unpublished it real quick, but you can still test from master branch if you need. I need to dig a little deeper though. Is this something you just noticed and thought was a problem, or was it the cause of an acutal bug / problem in your code? As long as your acquire callback does the correct thing, pool2 should "gain" the resource even if it never serves it to the acquire request that spawned it. |
You know... That's kind of what I thought it should do anyways. My max is "10". What I was seeing was 20+ open connections, using "netstat I've started looking through pool's code to understand why the 20 resources Thanks On Mon, Nov 14, 2016 at 12:49 PM Kris Reeves notifications@github.com
|
Okay, that definitely sounds like a bug. Can you reproduce it? Does it go away if you use the master branch as we thought? |
I can't seem to cause it to leak resources; timed out resources do decrement the internal counter of "pending" resources, but they also dispose of the resource so acquired. As best I can remember, this was a solution-of-least-change approach, rather than the optimal one I described above. I wrote a test to explicitly time out on acquire before the resource was returned, and the result, as long as the resource request completes (late), is that it is subsequently removed/cleaned up. |
I think it's maybe time for a rewrite, probably with a promise-based interface now that promises are in core... |
Pool 3? I'd be happy to collaborate. On Wed, Nov 16, 2016, 10:26 Kris Reeves notifications@github.com wrote:
|
Probably closer to pool2 2.0 :P I'll give some thought to what I'd want it to look like. The callbacks here definitely got more tangled than I originally hoped, and certainly more complex than the original version. I think promises would do a lot, but there are some other things I'd like to make into cleaner abstractions if I can. Meanwhile, if you're able to reproduce the "more resources than you should have" problem, I'd certainly like to try and fix it. |
Well... Since I moved my timeout into the acquire callback instead of On Wed, Nov 16, 2016, 12:11 Kris Reeves notifications@github.com wrote:
|
Might I ask you to share some code / put it back the way it was, so that I can run down the problem and fix it? |
Sure. I'll write up a sample and send it over. On Fri, Nov 18, 2016, 12:10 Kris Reeves notifications@github.com wrote:
|
Awesome, thanks! |
Attached is a sample using nothing more than a timeout to make sure the Note that the issue appears to be worse than I initially reported. Not sure On Fri, Nov 18, 2016 at 2:13 PM Kris Reeves notifications@github.com
|
Forgot that attachments don't work here. So, here is the code:
On Mon, Nov 21, 2016 at 4:38 PM Lucas Lacroix raijinsetsu@gmail.com wrote:
|
Fantastic, thanks. Somehow I thought it was a little trickier than that... will investigate. |
Apologies for taking so long to dig into this. From your code, I notice three things:
I think you chose exactly the correct solution: if what you want is to destroy the resource itself, e.g. terminate a TCP connection or whatever, after an amount of time, that behavior should be in the library you're binding; for example, with an http request, you might set an timeout on the socket and close the socket if it is exceeded. This timeout should trigger an error callback to pool2 itself, thus causing the resource acquisition to fail. It seems that possibly acquireTimeout is an ill-advised feature. The behavior as written is as intended, but the consequences are not clear. The solution I'm choosing for this issue is to update the documentation to help make it clearer: acquireTimeout is when pool2 will give up on waiting for the resource to arrive (it will be discarded if it arrives late or errors), but in-flight requests will not be capped to the max in this case. You will be guaranteed that only the max number of resources are available to your application at any given time. Thank you for bringing this to my attention! Please reopen if you determine this is not an adequate solution! |
Ok. So for my scenario, I should have a timeout on the connection and
acquire timeout should be infinity?
…On Sat, Dec 17, 2016, 13:54 Kris Reeves ***@***.***> wrote:
Closed #30 <#30>.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#30 (comment)>, or mute the
thread
<https://github.com/notifications/unsubscribe-auth/AGfltrONX4aBk63LXL8aIoY2GzpVZWzaks5rJC_egaJpZM4KvKiU>
.
|
Sounds right. |
The call to acquire can timeout, according to the acquireTimeout value. When Pool2 times out the action and tries again, there is nothing to stop the prior acquire attempt. This can lead to resource leakage. The only solution I can think of is to remove the acquireTimeout completely and handle the timeout myself.
Example of the issue:
If the SSL handshake does not complete within 2 seconds (but completes later), this stream is left open.
Is the only solution here to disable the acquireTimeout and handle the timeout myself within the acquire function?
The text was updated successfully, but these errors were encountered: