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
ensure connection is released #415
Conversation
Good point, but should we also close connection in case we have any error on |
@jettify but that's what the line that failed tried doing, closing it, and from what I saw on timeouts it tries to cancel the connection as well. |
btw CI seems to be failing due to something I did not change:
|
Regarding CI, I should have fix soon. |
Failed line tried to do |
Rebase should fix CI |
Codecov Report
@@ Coverage Diff @@
## master #415 +/- ##
=======================================
Coverage 93.53% 93.53%
=======================================
Files 25 25
Lines 3651 3651
Branches 194 194
=======================================
Hits 3415 3415
Misses 198 198
Partials 38 38 Continue to review full report at Codecov.
|
btw, let me know if you'd like to handle this via https://docs.python.org/3.5/library/contextlib.html#contextlib.ExitStack, I use it for situations like these to avoid code bloat |
I like ExitStack too but change is not significant probably not worth it. |
Regarding change, as you mentioned in other issue, we probably need to close connection, then return is back to the pool. Pool will drop it: Lines 250 to 261 in b301c9c
|
I worry about returning potentially broken connection to the pool. |
ok, so then what we need to do is create a new connection for the pool, let me c if I can come up with something |
no need to create connection, pool should care about that Lines 200 to 216 in b301c9c
|
with minsize == maxsize == 1: If we don't call release, and the connection never"closes" we're stuck because there are no "freeable" connections (default recycle is -1). If we do call release (like this patch does), and the connection never closes, we append a potentially bad connection to the pool. So I think we need "drop" ability to |
I mean close connection and release it back to the pool. Regardless of pool size connection should be always returned, it could be closed but should be returned. |
drop ability is here: Lines 249 to 250 in b301c9c
we stop tracking connection and do not move it to free connection list |
I'm not sure I'm following what you're saying but I've submitted a change which will allow non-closed connections to be dropped, let me know what you think. |
aiopg/pool.py
Outdated
if self._closing: | ||
conn.close() | ||
else: | ||
elif conn.closed: |
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.
Can you elaborate here? bit not follow in what case we need this?
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 just realized the fundamental premise of this function is to reuse connections, so there's a problem when we're passing connections that are in a bad state (thus I reverted last change).
Here's the issue which we need to resolve: conn.close() consistently throws an exception, how do we drop it? Right now we're going to call release, which will add it back to the free pool. If we don't call release it will be stuck in the used pool.
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.
Hold on but I thought that self._cur.close()
throws exception in your case not conn.close()
?
I am thinking more about:
|
ah, I was assuming that if the cursor close fails the connection close would fail as well, but ya I guess not, I'll code that up, thanks |
Glad to see you find some time to code between your parental responsibilities :) |
thanks, just sent you a link in gitter :) |
aiopg/utils.py
Outdated
@@ -145,7 +146,7 @@ class _PoolAcquireContextManager(_ContextManager): | |||
__slots__ = ('_coro', '_conn', '_pool') | |||
|
|||
def __init__(self, coro, pool): | |||
self._coro = coro | |||
super().__init__(coro) |
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.
not sure about this one, constructor also sets _obj property, it is not listed in slots, probably better have original version
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.
actually, this seems more correct, _obj
is used for __aenter__
/ __aexit__
in the parent class, and this is overriding the behavior and thus should be using the same attribute
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.
with even a further simplification :)
merged as part of #421 |
I've seen cases where the close can throw
psycopg2.ProgrammingError: close cannot be used while an asynchronous query is underway
which would previously cause the connection to not be returned to the pool, and cause a connection to "leak" from the pool. See discussion in: #364This also fixes running tests on OSX