fix(agent): preserve unsupported JDBC network timeout errors

Closes #5568
This commit is contained in:
t8y2 2026-08-07 10:42:12 +08:00
parent 518f60fc11
commit 1ac1b75f6d
No known key found for this signature in database
2 changed files with 56 additions and 1 deletions

View File

@ -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;

View File

@ -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,