Parent issue: #939
Scope
Fix the retry bypass where keyspace setup can fail synchronously on a defunct or otherwise unusable connection before RequestHandler installs its normal borrow callback.
The main observed path is:
HostConnectionPool.borrowConnection()
-> Connection.setKeyspaceAsync(...)
-> Connection.write(USE "<keyspace>")
-> ConnectionException: Write attempt on defunct connection
Because the exception is thrown before borrowConnection() returns a ListenableFuture, the request is wrapped as DriverInternalError instead of being retried on the next host.
Proposed Changes
- Make
Connection.setKeyspaceAsync() convert synchronous ConnectionException / BusyConnectionException from the internal USE write into a failed future.
- Reset
targetKeyspace when keyspace setup fails synchronously so future attempts are not blocked by a stale in-flight attempt.
- Ensure
HostConnectionPool.borrowConnection() restores inFlight / totalInFlight accounting when keyspace setup fails before the borrower receives a connection.
- Ensure
HostConnectionPool.dequeue() handles keyspace setup failures for pending borrows by completing the pending borrow with the failure and restoring connection counters.
- Consider skipping or re-checking defunct connections before keyspace setup after
inFlight is incremented.
Acceptance Criteria
- A defunct connection selected during
borrowConnection() keyspace setup returns a failed future instead of throwing synchronously.
RequestHandler reaches the existing onFailure() path and can try the next host when available.
- Pending borrows fail cleanly if keyspace setup fails during dequeue.
- Pool counters are restored on failed keyspace setup; no
inFlight / totalInFlight leak.
- Tests cover direct borrow and pending-borrow dequeue keyspace setup failures.
Parent issue: #939
Scope
Fix the retry bypass where keyspace setup can fail synchronously on a defunct or otherwise unusable connection before
RequestHandlerinstalls its normal borrow callback.The main observed path is:
Because the exception is thrown before
borrowConnection()returns aListenableFuture, the request is wrapped asDriverInternalErrorinstead of being retried on the next host.Proposed Changes
Connection.setKeyspaceAsync()convert synchronousConnectionException/BusyConnectionExceptionfrom the internalUSEwrite into a failed future.targetKeyspacewhen keyspace setup fails synchronously so future attempts are not blocked by a stale in-flight attempt.HostConnectionPool.borrowConnection()restoresinFlight/totalInFlightaccounting when keyspace setup fails before the borrower receives a connection.HostConnectionPool.dequeue()handles keyspace setup failures for pending borrows by completing the pending borrow with the failure and restoring connection counters.inFlightis incremented.Acceptance Criteria
borrowConnection()keyspace setup returns a failed future instead of throwing synchronously.RequestHandlerreaches the existingonFailure()path and can try the next host when available.inFlight/totalInFlightleak.