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
Fixes #638 Implement support for get/setNetworkTimeout(). #849
Conversation
@vlsi I am not sure why this was originally flagged as "concurrency hard". Ultimately, this call just boils down to a The primary purpose of the addtion to the JDBC specification was to prevent connections hung by unacknowledged TCP packets due to a network disruption. It is no substitue for a query timeout, and it is ultimately easy for a user to shoot themselves in the foot. Fortunately, most users rarely if ever call this directly (clearly pgjdbc users have never called it), but infrastructure libraries like HikariCP make use of it in a controlled manner. |
Codecov Report
@@ Coverage Diff @@
## master #849 +/- ##
============================================
+ Coverage 65.94% 65.95% +0.01%
- Complexity 3561 3567 +6
============================================
Files 166 166
Lines 15244 15264 +20
Branches 2465 2467 +2
============================================
+ Hits 10052 10067 +15
- Misses 4022 4025 +3
- Partials 1170 1172 +2 |
@brettwooldridge , the question is what would you do in case of TimeoutException? |
@vlsi Ah, that is actually a good question. I assumed the existing code paths would already handle socket-level errors. According to the JavaDoc:
If you want, I can investigate the various code paths to ensure that the exception is handled properly. EDIT: I kind of thought this handling was already in-place, as the driver supports socketTimeout. Both the socketTimeout and |
3180aef
to
08d8b47
Compare
@vlsi Well ouch, that was not a very happy string to pull. 😭 I thought I would throw in some unit tests. But this one is failing: try {
_conn.setNetworkTimeout(null, (int) TimeUnit.SECONDS.toMillis(1));
stmt = _conn.createStatement();
stmt.execute("SELECT pg_sleep(2)");
fail("Connection.setNetworkTimeout() did not throw expected exception");
}
catch (SQLException e) {
assertTrue(stmt.isClosed()); <--- HERE
assertTrue(_conn.isClosed());
} If that line is removed, the test passes. My assumption was that the So, then I added the assertion that the According to the JDBC Specification:
So looking at PgConnection:1190 I was expecting to find some kind of Statement tracking; I have to do something similar in HikariCP. However, it appears that none of the The lack of resource tracking precludes honoring the JDBC specification contracts, not only with regard to
What I propose is this:
EDIT: As a side note, it would be nice if pgjdbc supported the specific JDBC exception types such as |
This PR seems to be in limbo. Are there any plans to push forward with it? |
This is sort of up to @brettwooldridge ? |
@davecramer Should I interpret that to mean that the project owners approve of this change and will merge it once:
|
I'm going to say we won't consider it without it. That said I see no reason to not accept it. Although there was an outstanding question of how to handle the timeout exception. |
c71430a
to
b29fb22
Compare
@davecramer @kscaldef I have rebased and moved the NetworkTimeoutTest to the JDBC 4.1 suite. The issue of proper resource cleanup is independent of this pull request and is being tracked separately by #855. I do have a branch with changes that address that issue, but it is currently unfinished. |
@brettwooldridge can you also adjust the indentation so that checkstyle is happy? I'm guessing the other failure was a heisentest, but I'm not sure. Sorry to pester you about this, but this issue (failure to recover from a network outage) has bitten us multiple times, and I'd really love to see it fixed. |
@kscaldef Sure, I'll take a look this week; 5am here in Tokyo now. |
I think such a check is pointless. SecurityException is a perfectly reasonable exception to be thrown; better in fact than a SQLEception that wraps such an exception. Checked exceptions by their nature must be wrapped, but that is not true of unchecked exceptions. What should definitely not occur is to return from this method without setting the timeout and without throwing an exception. |
@brettwooldridge , well it's probably pointless, but the jdbc spec/javadoc requires it:
A simple check like this should do the trick: SecurityManager secMgr = System.getSecurityManager();
if (secMgr != null) {
secMgr.checkPermission(new SQLPermission("setNetworkTimeout"));
} |
Dave Cramer
On 1 October 2017 at 20:20, Jorge Solorzano ***@***.***> wrote:
@brettwooldridge <https://github.com/brettwooldridge> , well it's
probably pointless, but the jdbc spec/javadoc
<https://docs.oracle.com/javase/9/docs/api/java/sql/Connection.html#setNetworkTimeout-java.util.concurrent.Executor-int->
requires it:
This method checks to see that there is an SQLPermission object before
allowing the method to proceed. If a SecurityManager exists and its
checkPermission method denies calling setNetworkTimeout, this method throws
a java.lang.SecurityException.
A simple check like this should do the trick:
SecurityManager secMgr = System.getSecurityManager();if (secMgr != null) {
secMgr.checkPermission(new SQLPermission("setNetworkTimeout"));
}
won't it throw one anyway if you don't have permission ?
… —
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#849 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAYz9mI_noYU6XZ9AiMquM-nCw4lwbBkks5soCxJgaJpZM4OEWiD>
.
|
No, the driver has to explicitly check for it. |
On 1 October 2017 at 20:29, Jorge Solorzano ***@***.***> wrote:
won't it throw one anyway if you don't have permission ?
No, the driver has to explicitly check for it.
I'm confused. If no exception will be thrown if I don't check for it, why
check for it?
Dave Cramer
|
@davecramer , I'm not aware of the internals of the Security Manager, and in most applications a Security Manager policy is not used or enabled, but the JDBC spec requires that some methods do this check. There is a SQLPermission class that contains more info. |
@jorsol @davecramer There is no need to check this permission. The SecurityManager will throw a The only reason we would check if such a permission exists is in the case where the code would somehow need to behave differently upon denial. That is not the case with |
b29fb22
to
f9c086e
Compare
Checkstyle issues fixed for |
@brettwooldridge, I may have misunderstood how the SecurityManager works, but AFAIK this is an implementation code, not a consumer code, so in your case your fallback logic is as consumer code. I have checked some others drivers and they implement the check, and even the DriverManager wich is a class of the JDK has it. As I said, I have not yet tested it with a SecurityManager enabled, but I just want to be sure that the code works in compliance with what the JDBC spec says, so an additional check that might not be needed is better than an missing check that is needed. |
f9c086e
to
6bbd60c
Compare
@jorsol Ok, I'll buy that. Check added, consummate with checks done by other drivers. |
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.
Thanks! @brettwooldridge
@davecramer @kscaldef I believe this pull request is ready to go. |
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.
lgtm
Is there any reason to hold this on? Is there a tentative milestone to merge this? |
ping @vlsi any changes required to get this pulled in? |
+1 one for this, caused some concern in my team. |
Have you tested this PR ?
Dave Cramer
…On 10 November 2017 at 17:29, Dominic Gunn ***@***.***> wrote:
+1 one for this, caused some concern in my team.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#849 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAYz9ihCG13jzXgC_kO8HIDwYNadKhboks5s1M5XgaJpZM4OEWiD>
.
|
@davecramer I believe the integration test covers it well enough. |
🎉 |
Besides the usual bug fixes and optimizations, the more recent versions implement missing features like being able to set network timeouts to avoid connections hung due to network disruptions [1]. [1] pgjdbc/pgjdbc#849 Change-Id: Idb8b0376fc24b1d050b72057303c551d36fa931b
HikariCP logs a warning at connection pool startup when a driver is found to not support get/setNetworkTimeout() -- due to vulnerability to getting stuck during a network disruption or partition event.
Given our user-base of several hundred thousand users, the warning message has turned into a support burden, with users concerned about its meaning. One solution would be to do away with the warning, but that doesn't really serve the user.
So, here is the implementation of said feature -- I should have done this a year ago out of self-preservation.