From 9310adc74840aade692db86da28e95dcbe78b9b1 Mon Sep 17 00:00:00 2001 From: Thomas Segismont Date: Tue, 6 Apr 2021 15:42:48 +0200 Subject: [PATCH] Reactive DS idle-timeout for pooled connections Before Vert.x 3.9.6, the reactive SQL client pool implementation did not support idle-timeout. So we temporarily used the TCP connection idle-timeout config to achieve the same effect (with the caveat that the connection could be closed as idle after it was borrowed but not yet used for request execution). With https://github.com/quarkusio/quarkus/pull/16100, Quarkus uses Vert.x 3.9.6 so we can now apply the idle-timeout config at the pool level and get rid of the warnings in the doc. --- .../main/asciidoc/reactive-sql-clients.adoc | 25 +++---------------- .../DataSourceReactiveRuntimeConfig.java | 2 +- .../db2/client/runtime/DB2PoolRecorder.java | 10 ++++---- .../client/runtime/MySQLPoolRecorder.java | 10 ++++---- .../pg/client/runtime/PgPoolRecorder.java | 10 ++++---- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/docs/src/main/asciidoc/reactive-sql-clients.adoc b/docs/src/main/asciidoc/reactive-sql-clients.adoc index bf0ad6b551166..d7899e4d71de5 100644 --- a/docs/src/main/asciidoc/reactive-sql-clients.adoc +++ b/docs/src/main/asciidoc/reactive-sql-clients.adoc @@ -616,9 +616,10 @@ In `application.properties` add: quarkus.datasource.reactive.url=mysql:///quarkus_test?host=/var/run/mysqld/mysqld.sock ---- -== TCP Connection `idle-timeout` +== Pooled Connection `idle-timeout` -Reactive datasources can be configured with an `idle-timeout` (in milliseconds) that applies at the TCP connection level. +Reactive datasources can be configured with an `idle-timeout` (in milliseconds). +It is the maximum time a connection remains unused in the pool before it is closed. NOTE: The `idle-timeout` is disabled by default. @@ -629,26 +630,6 @@ For example, you could expire idle connections after 60 minutes: quarkus.datasource.reactive.idle-timeout=PT60M ---- -[WARNING] -==== -This timeout does not apply to the pool, but to the TCP connection. - -If it expires while the connection is idle in the pool, the connection is closed and removed from the pool. - -If it expires immediately after your borrowed the connection from the pool and before you execute a query, you will get an error. - - -While this is unlikely to happen, you must be prepared for such eventuality: - -[source,java] ----- -// Run a query, retry at most 3 times if it fails -Uni> rowSet = client.query("SELECT id, name FROM fruits ORDER BY name ASC") - .execute() - .onFailure().retry().atMost(3); ----- -==== - == Configuration Reference === Common Datasource diff --git a/extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/DataSourceReactiveRuntimeConfig.java b/extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/DataSourceReactiveRuntimeConfig.java index 5e0770fd8e643..641b819c3bfd6 100644 --- a/extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/DataSourceReactiveRuntimeConfig.java +++ b/extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/DataSourceReactiveRuntimeConfig.java @@ -110,7 +110,7 @@ public class DataSourceReactiveRuntimeConfig { public Duration reconnectInterval = Duration.ofSeconds(1L); /** - * The maximum time without data written to or read from a connection before it is closed. + * The maximum time a connection remains unused in the pool before it is closed. */ @ConfigItem(defaultValueDocumentation = "no timeout") public Optional idleTimeout = Optional.empty(); diff --git a/extensions/reactive-db2-client/runtime/src/main/java/io/quarkus/reactive/db2/client/runtime/DB2PoolRecorder.java b/extensions/reactive-db2-client/runtime/src/main/java/io/quarkus/reactive/db2/client/runtime/DB2PoolRecorder.java index 2063f9fa06a6f..14376023144be 100644 --- a/extensions/reactive-db2-client/runtime/src/main/java/io/quarkus/reactive/db2/client/runtime/DB2PoolRecorder.java +++ b/extensions/reactive-db2-client/runtime/src/main/java/io/quarkus/reactive/db2/client/runtime/DB2PoolRecorder.java @@ -77,6 +77,11 @@ private PoolOptions toPoolOptions(DataSourceRuntimeConfig dataSourceRuntimeConfi poolOptions.setMaxSize(dataSourceReactiveRuntimeConfig.maxSize.getAsInt()); } + if (dataSourceReactiveRuntimeConfig.idleTimeout.isPresent()) { + int idleTimeout = Math.toIntExact(dataSourceReactiveRuntimeConfig.idleTimeout.get().toMillis()); + poolOptions.setIdleTimeout(idleTimeout).setIdleTimeoutUnit(TimeUnit.MILLISECONDS); + } + return poolOptions; } @@ -144,11 +149,6 @@ private DB2ConnectOptions toConnectOptions(DataSourceRuntimeConfig dataSourceRun connectOptions.setReconnectInterval(dataSourceReactiveRuntimeConfig.reconnectInterval.toMillis()); - if (dataSourceReactiveRuntimeConfig.idleTimeout.isPresent()) { - int idleTimeout = Math.toIntExact(dataSourceReactiveRuntimeConfig.idleTimeout.get().toMillis()); - connectOptions.setIdleTimeout(idleTimeout).setIdleTimeoutUnit(TimeUnit.MILLISECONDS); - } - return connectOptions; } } diff --git a/extensions/reactive-mysql-client/runtime/src/main/java/io/quarkus/reactive/mysql/client/runtime/MySQLPoolRecorder.java b/extensions/reactive-mysql-client/runtime/src/main/java/io/quarkus/reactive/mysql/client/runtime/MySQLPoolRecorder.java index 4bd4ae1e74d42..38eeaa87e1bb5 100644 --- a/extensions/reactive-mysql-client/runtime/src/main/java/io/quarkus/reactive/mysql/client/runtime/MySQLPoolRecorder.java +++ b/extensions/reactive-mysql-client/runtime/src/main/java/io/quarkus/reactive/mysql/client/runtime/MySQLPoolRecorder.java @@ -78,6 +78,11 @@ private PoolOptions toPoolOptions(DataSourceRuntimeConfig dataSourceRuntimeConfi poolOptions.setMaxSize(dataSourceReactiveRuntimeConfig.maxSize.getAsInt()); } + if (dataSourceReactiveRuntimeConfig.idleTimeout.isPresent()) { + int idleTimeout = Math.toIntExact(dataSourceReactiveRuntimeConfig.idleTimeout.get().toMillis()); + poolOptions.setIdleTimeout(idleTimeout).setIdleTimeoutUnit(TimeUnit.MILLISECONDS); + } + return poolOptions; } @@ -153,11 +158,6 @@ private MySQLConnectOptions toMySQLConnectOptions(DataSourceRuntimeConfig dataSo mysqlConnectOptions.setReconnectInterval(dataSourceReactiveRuntimeConfig.reconnectInterval.toMillis()); - if (dataSourceReactiveRuntimeConfig.idleTimeout.isPresent()) { - int idleTimeout = Math.toIntExact(dataSourceReactiveRuntimeConfig.idleTimeout.get().toMillis()); - mysqlConnectOptions.setIdleTimeout(idleTimeout).setIdleTimeoutUnit(TimeUnit.MILLISECONDS); - } - return mysqlConnectOptions; } diff --git a/extensions/reactive-pg-client/runtime/src/main/java/io/quarkus/reactive/pg/client/runtime/PgPoolRecorder.java b/extensions/reactive-pg-client/runtime/src/main/java/io/quarkus/reactive/pg/client/runtime/PgPoolRecorder.java index 7cbee0906394b..c1dc0f2ac5824 100644 --- a/extensions/reactive-pg-client/runtime/src/main/java/io/quarkus/reactive/pg/client/runtime/PgPoolRecorder.java +++ b/extensions/reactive-pg-client/runtime/src/main/java/io/quarkus/reactive/pg/client/runtime/PgPoolRecorder.java @@ -78,6 +78,11 @@ private PoolOptions toPoolOptions(DataSourceRuntimeConfig dataSourceRuntimeConfi poolOptions.setMaxSize(dataSourceReactiveRuntimeConfig.maxSize.getAsInt()); } + if (dataSourceReactiveRuntimeConfig.idleTimeout.isPresent()) { + int idleTimeout = Math.toIntExact(dataSourceReactiveRuntimeConfig.idleTimeout.get().toMillis()); + poolOptions.setIdleTimeout(idleTimeout).setIdleTimeoutUnit(TimeUnit.MILLISECONDS); + } + return poolOptions; } @@ -151,11 +156,6 @@ private PgConnectOptions toPgConnectOptions(DataSourceRuntimeConfig dataSourceRu pgConnectOptions.setReconnectInterval(dataSourceReactiveRuntimeConfig.reconnectInterval.toMillis()); - if (dataSourceReactiveRuntimeConfig.idleTimeout.isPresent()) { - int idleTimeout = Math.toIntExact(dataSourceReactiveRuntimeConfig.idleTimeout.get().toMillis()); - pgConnectOptions.setIdleTimeout(idleTimeout).setIdleTimeoutUnit(TimeUnit.MILLISECONDS); - } - return pgConnectOptions; } }