You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The fix correctly identifies and addresses the root cause: without ASYNC_OPERATIONS=true, runAsyncOperation wraps the supplier in CompletableFuture.completedFuture(resultSupplier.get()), which executes the HTTP request synchronously before returning the future. Calling .get(timeout, unit) on an already-completed future can never throw TimeoutException. Setting ASYNC_OPERATIONS=true dispatches to a thread pool so the future is genuinely interruptible.
Good approach overall, but there are several issues to address:
Issues
1. Fix is incomplete — executeUpdateImpl still has the same bug
executeUpdateImpl at StatementImpl.java:251 uses .get(queryTimeout, TimeUnit.SECONDS) without ASYNC_OPERATIONS=true, so executeUpdate/executeLargeUpdate calls will still never time out:
// StatementImpl.java:251-252 — same problem as the original bugtry (QueryResponseresponse = queryTimeout == 0 ? connection.getClient().query(lastStatementSql, mergedSettings).get()
: connection.getClient().query(lastStatementSql, mergedSettings).get(queryTimeout, TimeUnit.SECONDS)) {
The same ASYNC_OPERATIONS flag must be applied here. Fix this →
2. Resource leak when timeout fires
When .get(queryTimeout, TimeUnit.SECONDS) throws TimeoutException, the CompletableFuture reference is discarded and response is null. The background thread continues executing the HTTP request, and the QueryResponse it eventually produces is never closed — leaking the underlying HTTP connection back to the pool.
The fix should keep a reference to the future and attach a cleanup callback:
CompletableFuture<QueryResponse> future = connection.getClient().query(lastStatementSql,
mergedSettings.setOption(ClientConfigProperties.ASYNC_OPERATIONS.getKey(), true));
try {
response = future.get(queryTimeout, TimeUnit.SECONDS);
} catch (TimeoutExceptione) {
// Clean up the response when the background task eventually finishesfuture.whenComplete((r, ex) -> {
if (r != null) {
try { r.close(); } catch (Exceptionignore) {}
}
});
throwe;
}
PreparedStatementTest.java:572 — the test relies on MD5 + sum over 1M rows taking longer than 1 second. On fast CI runners this might complete in < 1s, causing assertThrows to fail because no exception is thrown. A deterministic alternative:
// Use sleep() to guarantee the query exceeds the timeoutfinalStringsql = "SELECT sleep(3)";
Or increase the LIMIT significantly (e.g., LIMIT 100000000) to make the query reliably slow.
4. Unused import in test file
PreparedStatementTest.java:3 imports ClientConfigProperties but it is not referenced anywhere in the file. Fix this →
5. No server-side query cancellation on timeout
After the client-side timeout fires, the ClickHouse server continues executing the query indefinitely (until max_execution_time expires server-side, or the connection drops). This is a known trade-off, but it may be worth adding a comment or, optionally, calling KILL QUERY in the timeout path (similar to how cancel() already works). At a minimum, consider documenting this behavior.
Minor: Code style
The inline mergedSettings.setOption(...) passed directly into the query() call is a little subtle since it mutates mergedSettings as a side-effect of passing it:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #2637
Checklist
Delete items not relevant to your PR: