Conversation
Add an application-level keep-alive mechanism to the SQL connection pool so connections silently dropped while idle (e.g. by a load balancer or the database) are detected and replaced, instead of failing the next query with a connection error. When a pooled connection has been idle for at least a configurable interval, the pool issues a lightweight probe statement against it before handing it to a caller. If the probe fails because the connection is stale, the pool closes it (removing it via the connector onRemove callback, since ConnectionPool.evict only removes unused connections) and transparently retries the command on a fresh connection, bounded by MAX_KEEPALIVE_RETRIES. Core (vertx-sql-client): - PoolOptions.idleKeepAlive / setIdleKeepAlive (default 0 = disabled) - PingCommand carrying the configurable probe statement - Connection.keepAliveQuery() SPI; the pool issues it on checkout and recovers from stale connections in execute() PostgreSQL (vertx-pg-client): - PgConnectOptions.keepAliveQuery (default 'SELECT 1'), implemented by PgSocketConnection and encoded as a simple query on the wire Tests (PgPoolKeepAliveTest): - a healthy idle connection is kept alive (same backend PID) - a connection dropped at the network level via ProxyServer recovers transparently on a fresh backend Signed-off-by: Vasily Pelikh <vasily.pelikh@gmail.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
Adds an application-level keep-alive mechanism to the SQL connection pool so connections that are silently dropped while idle (for example by an intermediate load balancer or the database itself) are detected and replaced with a fresh connection instead of failing the next user query with a
Connection timed outerror.The mechanism works in two parts:
Changes
Core (
vertx-sql-client)PoolOptions.idleKeepAlive/setIdleKeepAlive(with unit, default0= disabled). Configures how long a pooled connection can be idle before it is probed.spi/protocol/PingCommand— a probe command carrying the lightweight statement used to verify liveness.Connection.keepAliveQuery()SPI — the pool reads the probe statement from the connection, keeping the pool database-agnostic.PoolImpl/SqlConnectionPool):probeIfNeededissues thePingCommandon checkout when the idle threshold is exceeded; on failure it closes the stale connection, which removes it from the pool via the connectoronRemovecallback (ConnectionPool.evictonly removes unused connections, so a leased stale one must be closed instead).executetransparently retries the command on a fresh connection, bounded byMAX_KEEPALIVE_RETRIES.PostgreSQL (
vertx-pg-client)PgConnectOptions.keepAliveQuery— the probe statement is moved to configuration (defaultSELECT 1).PgSocketConnectionimplementskeepAliveQuery()and encodes aPingCommandas a simple query on the wire.Tests
PgPoolKeepAliveTest:ProxyServer, simulating a load-balancer silent close) recovers transparently on a fresh backend.Why an application-level probe
TCP keep-alive alone is often insufficient: load balancers can drop idle connections without sending a reset, and OS keep-alive intervals are long. An application-level probe actively verifies the connection is usable right before it is used, directly addressing idle stale-connection failures.
Design notes
idleKeepAlive = 0), so no behaviour change for existing users.PgConnectOptions.keepAliveQuery), so each database can provide a correct, portable no-op statement.Interaction with the
vertx-coreconnection poolThe stale-connection handling is scoped to the SQL client and deliberately does not change the
vertx-coreconnection pool:ConnectionPool.evict(...)only removes unused connections (usage == 0). That is an intentional contract ofvertx-core, so evicting a stale leased connection there would change public pooling semantics.vertx-coremechanism: when the probe fails, the SQL pool closes the stale connection, which fires the connectoronRemove()callback.vertx-core'sRemoveaction handles a leased connection correctly — it drops it and, if a waiter is queued, immediately connects a replacement.This keeps the fix localized to
vertx-sql-clientand preserves allvertx-corepool guarantees.