fix(agent): preserve unsupported JDBC network timeout errors
Closes #5568
This commit is contained in:
parent
518f60fc11
commit
1ac1b75f6d
|
|
@ -1475,7 +1475,7 @@ final class JdbcConnectionPoolRegistry implements AutoCloseable {
|
|||
call("physical_set_network_timeout", () -> {
|
||||
connection.setNetworkTimeout(networkTimeoutExecutor, networkTimeoutMillis);
|
||||
return null;
|
||||
}, factoryDataSource, timeoutMillis);
|
||||
}, factoryDataSource, timeoutMillis, true);
|
||||
}
|
||||
|
||||
private <T> T call(
|
||||
|
|
@ -1483,6 +1483,16 @@ final class JdbcConnectionPoolRegistry implements AutoCloseable {
|
|||
PhysicalConnectionCall<T> call,
|
||||
ConnectionFactoryDataSource factoryDataSource,
|
||||
long timeoutMillis
|
||||
) throws SQLException {
|
||||
return call(operation, call, factoryDataSource, timeoutMillis, false);
|
||||
}
|
||||
|
||||
private <T> T call(
|
||||
String operation,
|
||||
PhysicalConnectionCall<T> call,
|
||||
ConnectionFactoryDataSource factoryDataSource,
|
||||
long timeoutMillis,
|
||||
boolean preserveCompletedFailure
|
||||
) throws SQLException {
|
||||
CompletableFuture<T> outcome = new CompletableFuture<>();
|
||||
try {
|
||||
|
|
@ -1511,6 +1521,13 @@ final class JdbcConnectionPoolRegistry implements AutoCloseable {
|
|||
factoryDataSource.poison(failure);
|
||||
throw failure;
|
||||
} catch (ExecutionException error) {
|
||||
if (preserveCompletedFailure) {
|
||||
Throwable cause = error.getCause();
|
||||
if (cause instanceof SQLException sqlError) {
|
||||
throw sqlError;
|
||||
}
|
||||
throw new SQLException("JDBC physical operation failed: " + operation, cause);
|
||||
}
|
||||
SQLException failure = new PhysicalConnectionStateUnknownException(error.getCause());
|
||||
factoryDataSource.poison(failure);
|
||||
throw failure;
|
||||
|
|
|
|||
|
|
@ -850,6 +850,27 @@ class JdbcConnectionPoolingTest {
|
|||
}
|
||||
}
|
||||
|
||||
@RepeatedTest(5)
|
||||
void unsupportedNetworkTimeoutDoesNotPoisonIdentity() throws Exception {
|
||||
AtomicInteger physicalOpens = new AtomicInteger();
|
||||
String url = h2Url("unsupported_network_timeout");
|
||||
try (Connection ignored = openH2(url, physicalOpens)) {
|
||||
// Keep H2 bootstrap outside the setup classification watchdog.
|
||||
}
|
||||
physicalOpens.set(0);
|
||||
try (JdbcConnectionPoolRegistry registry = new JdbcConnectionPoolRegistry(shortTimeoutPoolSettings(1, 32))) {
|
||||
for (int attempt = 0; attempt < 2; attempt++) {
|
||||
try (JdbcConnectionPoolRegistry.Lease lease = registry.borrow(
|
||||
"unsupported-network-timeout",
|
||||
() -> unsupportedNetworkTimeoutConnection(openH2(url, physicalOpens))
|
||||
)) {
|
||||
assertTrue(lease.connection().isValid(1));
|
||||
}
|
||||
}
|
||||
assertEquals(1, physicalOpens.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void blockedSetupAfterKnownFailurePoisonsCurrentAttemptGeneration() throws Exception {
|
||||
AtomicInteger connectionAttempts = new AtomicInteger();
|
||||
|
|
@ -2136,6 +2157,23 @@ class JdbcConnectionPoolingTest {
|
|||
);
|
||||
}
|
||||
|
||||
private static Connection unsupportedNetworkTimeoutConnection(Connection delegate) {
|
||||
return (Connection) Proxy.newProxyInstance(
|
||||
Connection.class.getClassLoader(),
|
||||
new Class<?>[] {Connection.class},
|
||||
(proxy, method, args) -> {
|
||||
if ("setNetworkTimeout".equals(method.getName())) {
|
||||
throw new SQLException("Does not support setNetworkTimeout");
|
||||
}
|
||||
try {
|
||||
return method.invoke(delegate, args);
|
||||
} catch (InvocationTargetException error) {
|
||||
throw error.getCause();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static Connection asynchronousAbortConnection(
|
||||
Connection delegate,
|
||||
CountDownLatch abortScheduled,
|
||||
|
|
|
|||
Loading…
Reference in New Issue