Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support config reactive datasource with list of database urls for fault tolerance and load balance #31994

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c2bf298
support config reactive datasource with list of urls
benstonezhang Mar 21, 2023
f393ecf
revised comments; add test for db2, mssql and pg
benstonezhang Mar 23, 2023
f4ac273
Fix OTel exporter headers config
brunobat Mar 23, 2023
075a586
Ensure Dialects initialized by the Hibernate Reactive extension use t…
Sanne Mar 23, 2023
35b333f
Update SmallRye Config to 3.2.0
radcortez Mar 13, 2023
9fb6afd
Update SmallRye Config to 3.2.0
radcortez Mar 23, 2023
378dbb6
DevUI: Liquibase
melloware Mar 23, 2023
cf2c950
Bump mariadb-java-client from 3.1.2 to 3.1.3
dependabot[bot] Mar 23, 2023
2e02dcc
Bump smallrye-open-api.version from 3.3.0 to 3.3.1
dependabot[bot] Mar 24, 2023
7adf923
Merge remote-tracking branch 'origin/main' into reactive-db-conn-pool
benstonezhang Mar 24, 2023
478c660
revert change made for db2 and mssql; update warning for multi values…
benstonezhang Mar 24, 2023
b3b5c03
Allow using the annotation `@PartFilename` on method parameters
Sgitario Mar 24, 2023
e6baa3c
Fix Kotlin formatting
geoand Mar 24, 2023
14d12e8
Merge pull request #32086 from Sanne/HRDialectWrapping
yrodiere Mar 24, 2023
09fb411
Merge pull request #31824 from radcortez/srconfig-3.2.0
gsmet Mar 24, 2023
b4a92c8
Merge pull request #32091 from melloware/devui-liquibase
phillip-kruger Mar 24, 2023
125f884
Merge pull request #32100 from geoand/kotlin
gsmet Mar 24, 2023
d15dff6
Merge pull request #32073 from brunobat/fix-header-docs
radcortez Mar 24, 2023
1d53bbf
Merge pull request #32099 from Sgitario/32033
Sgitario Mar 24, 2023
66c9dd2
Merge pull request #32094 from quarkusio/dependabot/maven/org.mariadb…
gsmet Mar 24, 2023
2647d64
Merge pull request #32095 from quarkusio/dependabot/maven/smallrye-op…
gsmet Mar 24, 2023
0ddddfb
support config reactive datasource with list of urls
benstonezhang Mar 21, 2023
28ad2ce
revised comments; add test for db2, mssql and pg
benstonezhang Mar 23, 2023
42a6232
revert change made for db2 and mssql; update warning for multi values…
benstonezhang Mar 24, 2023
6eb3c0f
Merge remote-tracking branch 'origin/reactive-db-conn-pool' into reac…
benstonezhang Mar 24, 2023
c0f173d
support config reactive datasource with list of urls
benstonezhang Mar 21, 2023
7bed2ce
revised comments; add test for db2, mssql and pg
benstonezhang Mar 23, 2023
8e54ba3
revert change made for db2 and mssql; update warning for multi values…
benstonezhang Mar 24, 2023
5a963dc
Merge branch 'reactive-db-conn-pool' of https://github.com/benstonezh…
benstonezhang Mar 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
Expand All @@ -23,10 +24,10 @@ public class DataSourceReactiveRuntimeConfig {
public boolean cachePreparedStatements = false;

/**
* The datasource URL.
* The datasource URLs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a comment explaining that if multiple values are set, then the pool will be configured to create new connections using each of the urls, in a round-robin fashion?

*/
@ConfigItem
public Optional<String> url = Optional.empty();
public Optional<List<String>> url = Optional.empty();

/**
* The datasource pool maximum size.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.reactive.db2.client;

import java.util.List;

import io.quarkus.reactive.datasource.ReactiveDataSource;
import io.vertx.core.Vertx;
import io.vertx.db2client.DB2ConnectOptions;
Expand All @@ -25,6 +27,6 @@ interface Input {

PoolOptions poolOptions();

DB2ConnectOptions db2ConnectOptions();
List<DB2ConnectOptions> db2ConnectOptionsList();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For DB2, we should do the same as with Oracle (only log a warning if the user provides two or more urls).

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePfxKeyCertOptions;
import static io.quarkus.vertx.core.runtime.SSLConfigHelper.configurePfxTrustOptions;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
Expand Down Expand Up @@ -71,16 +73,16 @@ private DB2Pool initialize(Vertx vertx,
DataSourceReactiveDB2Config dataSourceReactiveDB2Config) {
PoolOptions poolOptions = toPoolOptions(eventLoopCount, dataSourceRuntimeConfig, dataSourceReactiveRuntimeConfig,
dataSourceReactiveDB2Config);
DB2ConnectOptions connectOptions = toConnectOptions(dataSourceRuntimeConfig, dataSourceReactiveRuntimeConfig,
dataSourceReactiveDB2Config);
List<DB2ConnectOptions> connectOptionsList = toConnectOptions(dataSourceRuntimeConfig,
dataSourceReactiveRuntimeConfig, dataSourceReactiveDB2Config);

// Use the convention defined by Quarkus Micrometer Vert.x metrics to create metrics prefixed with db2. and
// the client_name as tag.
// See io.quarkus.micrometer.runtime.binder.vertx.VertxMeterBinderAdapter.extractPrefix and
// io.quarkus.micrometer.runtime.binder.vertx.VertxMeterBinderAdapter.extractClientName
connectOptions.setMetricsName("db2|" + dataSourceName);
connectOptionsList.forEach(connectOptions -> connectOptions.setMetricsName("db2|" + dataSourceName));

return createPool(vertx, poolOptions, connectOptions, dataSourceName);
return createPool(vertx, poolOptions, connectOptionsList, dataSourceName);
}

private PoolOptions toPoolOptions(Integer eventLoopCount,
Expand Down Expand Up @@ -113,75 +115,73 @@ private PoolOptions toPoolOptions(Integer eventLoopCount,
return poolOptions;
}

private DB2ConnectOptions toConnectOptions(DataSourceRuntimeConfig dataSourceRuntimeConfig,
private List<DB2ConnectOptions> toConnectOptions(DataSourceRuntimeConfig dataSourceRuntimeConfig,
DataSourceReactiveRuntimeConfig dataSourceReactiveRuntimeConfig,
DataSourceReactiveDB2Config dataSourceReactiveDB2Config) {
DB2ConnectOptions connectOptions;
List<DB2ConnectOptions> connectOptionsList = new ArrayList<>();

if (dataSourceReactiveRuntimeConfig.url.isPresent()) {
String url = dataSourceReactiveRuntimeConfig.url.get();
// clean up the URL to make migrations easier
if (url.matches("^vertx-reactive:db2://.*$")) {
url = url.substring("vertx-reactive:".length());
}
connectOptions = DB2ConnectOptions.fromUri(url);
List<String> urls = dataSourceReactiveRuntimeConfig.url.get();
urls.forEach(url -> {
// clean up the URL to make migrations easier
if (url.matches("^vertx-reactive:db2://.*$")) {
url = url.substring("vertx-reactive:".length());
}
connectOptionsList.add(DB2ConnectOptions.fromUri(url));
});
} else {
connectOptions = new DB2ConnectOptions();
connectOptionsList.add(new DB2ConnectOptions());
}

if (dataSourceRuntimeConfig.username.isPresent()) {
connectOptions.setUser(dataSourceRuntimeConfig.username.get());
}

if (dataSourceRuntimeConfig.password.isPresent()) {
connectOptions.setPassword(dataSourceRuntimeConfig.password.get());
}

// credentials provider
if (dataSourceRuntimeConfig.credentialsProvider.isPresent()) {
String beanName = dataSourceRuntimeConfig.credentialsProviderName.orElse(null);
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
String name = dataSourceRuntimeConfig.credentialsProvider.get();
Map<String, String> credentials = credentialsProvider.getCredentials(name);
String user = credentials.get(USER_PROPERTY_NAME);
String password = credentials.get(PASSWORD_PROPERTY_NAME);
if (user != null) {
connectOptions.setUser(user);
}
if (password != null) {
connectOptions.setPassword(user);
connectOptionsList.forEach(connectOptions -> {
dataSourceRuntimeConfig.username.ifPresent(connectOptions::setUser);

dataSourceRuntimeConfig.password.ifPresent(connectOptions::setPassword);

// credentials provider
if (dataSourceRuntimeConfig.credentialsProvider.isPresent()) {
String beanName = dataSourceRuntimeConfig.credentialsProviderName.orElse(null);
CredentialsProvider credentialsProvider = CredentialsProviderFinder.find(beanName);
String name = dataSourceRuntimeConfig.credentialsProvider.get();
Map<String, String> credentials = credentialsProvider.getCredentials(name);
String user = credentials.get(USER_PROPERTY_NAME);
String password = credentials.get(PASSWORD_PROPERTY_NAME);
if (user != null) {
connectOptions.setUser(user);
}
if (password != null) {
connectOptions.setPassword(password);
}
}
}

connectOptions.setCachePreparedStatements(dataSourceReactiveRuntimeConfig.cachePreparedStatements);
connectOptions.setCachePreparedStatements(dataSourceReactiveRuntimeConfig.cachePreparedStatements);

connectOptions.setSsl(dataSourceReactiveDB2Config.ssl);
connectOptions.setSsl(dataSourceReactiveDB2Config.ssl);

connectOptions.setTrustAll(dataSourceReactiveRuntimeConfig.trustAll);
connectOptions.setTrustAll(dataSourceReactiveRuntimeConfig.trustAll);

configurePemTrustOptions(connectOptions, dataSourceReactiveRuntimeConfig.trustCertificatePem);
configureJksTrustOptions(connectOptions, dataSourceReactiveRuntimeConfig.trustCertificateJks);
configurePfxTrustOptions(connectOptions, dataSourceReactiveRuntimeConfig.trustCertificatePfx);
configurePemTrustOptions(connectOptions, dataSourceReactiveRuntimeConfig.trustCertificatePem);
configureJksTrustOptions(connectOptions, dataSourceReactiveRuntimeConfig.trustCertificateJks);
configurePfxTrustOptions(connectOptions, dataSourceReactiveRuntimeConfig.trustCertificatePfx);

configurePemKeyCertOptions(connectOptions, dataSourceReactiveRuntimeConfig.keyCertificatePem);
configureJksKeyCertOptions(connectOptions, dataSourceReactiveRuntimeConfig.keyCertificateJks);
configurePfxKeyCertOptions(connectOptions, dataSourceReactiveRuntimeConfig.keyCertificatePfx);
configurePemKeyCertOptions(connectOptions, dataSourceReactiveRuntimeConfig.keyCertificatePem);
configureJksKeyCertOptions(connectOptions, dataSourceReactiveRuntimeConfig.keyCertificateJks);
configurePfxKeyCertOptions(connectOptions, dataSourceReactiveRuntimeConfig.keyCertificatePfx);

connectOptions.setReconnectAttempts(dataSourceReactiveRuntimeConfig.reconnectAttempts);
connectOptions.setReconnectAttempts(dataSourceReactiveRuntimeConfig.reconnectAttempts);

connectOptions.setReconnectInterval(dataSourceReactiveRuntimeConfig.reconnectInterval.toMillis());
connectOptions.setReconnectInterval(dataSourceReactiveRuntimeConfig.reconnectInterval.toMillis());

if (dataSourceReactiveRuntimeConfig.hostnameVerificationAlgorithm.isPresent()) {
connectOptions.setHostnameVerificationAlgorithm(
dataSourceReactiveRuntimeConfig.hostnameVerificationAlgorithm.get());
}
dataSourceReactiveRuntimeConfig.hostnameVerificationAlgorithm.ifPresent(
connectOptions::setHostnameVerificationAlgorithm);

dataSourceReactiveRuntimeConfig.additionalProperties.forEach(connectOptions::addProperty);
dataSourceReactiveRuntimeConfig.additionalProperties.forEach(connectOptions::addProperty);
});

return connectOptions;
return connectOptionsList;
}

private DB2Pool createPool(Vertx vertx, PoolOptions poolOptions, DB2ConnectOptions dB2ConnectOptions,
private DB2Pool createPool(Vertx vertx, PoolOptions poolOptions, List<DB2ConnectOptions> dB2ConnectOptionsList,
String dataSourceName) {
Instance<DB2PoolCreator> instance;
if (DataSourceUtil.isDefault(dataSourceName)) {
Expand All @@ -191,21 +191,21 @@ private DB2Pool createPool(Vertx vertx, PoolOptions poolOptions, DB2ConnectOptio
new ReactiveDataSource.ReactiveDataSourceLiteral(dataSourceName));
}
if (instance.isResolvable()) {
DB2PoolCreator.Input input = new DefaultInput(vertx, poolOptions, dB2ConnectOptions);
DB2PoolCreator.Input input = new DefaultInput(vertx, poolOptions, dB2ConnectOptionsList);
return instance.get().create(input);
}
return DB2Pool.pool(vertx, dB2ConnectOptions, poolOptions);
return DB2Pool.pool(vertx, dB2ConnectOptionsList, poolOptions);
}

private static class DefaultInput implements DB2PoolCreator.Input {
private final Vertx vertx;
private final PoolOptions poolOptions;
private final DB2ConnectOptions dB2ConnectOptions;
private final List<DB2ConnectOptions> dB2ConnectOptionsList;

public DefaultInput(Vertx vertx, PoolOptions poolOptions, DB2ConnectOptions dB2ConnectOptions) {
public DefaultInput(Vertx vertx, PoolOptions poolOptions, List<DB2ConnectOptions> dB2ConnectOptionsList) {
this.vertx = vertx;
this.poolOptions = poolOptions;
this.dB2ConnectOptions = dB2ConnectOptions;
this.dB2ConnectOptionsList = dB2ConnectOptionsList;
}

@Override
Expand All @@ -219,8 +219,8 @@ public PoolOptions poolOptions() {
}

@Override
public DB2ConnectOptions db2ConnectOptions() {
return dB2ConnectOptions;
public List<DB2ConnectOptions> db2ConnectOptionsList() {
return dB2ConnectOptionsList;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class LocalhostMSSQLPoolCreator implements MSSQLPoolCreator {

@Override
public MSSQLPool create(Input input) {
return MSSQLPool.pool(input.vertx(), input.msSQLConnectOptions().setHost("localhost").setPort(1435),
return MSSQLPool.pool(input.vertx(), input.msSQLConnectOptionsList().get(0).setHost("localhost").setPort(1435),
input.poolOptions());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ public static class DefaultMSSQLPoolCreator implements MSSQLPoolCreator {

@Override
public MSSQLPool create(Input input) {
assertEquals(12345, input.msSQLConnectOptions().getPort()); // validate that the bean has been called for the proper datasource
return MSSQLPool.pool(input.vertx(), input.msSQLConnectOptions().setHost("localhost").setPort(1435),
assertEquals(12345, input.msSQLConnectOptionsList().get(0).getPort()); // validate that the bean has been called for the proper datasource
return MSSQLPool.pool(input.vertx(), input.msSQLConnectOptionsList().get(0).setHost("localhost").setPort(1435),
input.poolOptions());
}
}
Expand All @@ -97,8 +97,8 @@ public static class HibernateMSSQLPoolCreator implements MSSQLPoolCreator {

@Override
public MSSQLPool create(Input input) {
assertEquals(55555, input.msSQLConnectOptions().getPort()); // validate that the bean has been called for the proper datasource
return MSSQLPool.pool(input.vertx(), input.msSQLConnectOptions().setHost("localhost").setPort(1435),
assertEquals(55555, input.msSQLConnectOptionsList().get(0).getPort()); // validate that the bean has been called for the proper datasource
return MSSQLPool.pool(input.vertx(), input.msSQLConnectOptionsList().get(0).setHost("localhost").setPort(1435),
input.poolOptions());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static class AnotherMSSQLPoolCreator implements MSSQLPoolCreator {

@Override
public MSSQLPool create(Input input) {
return MSSQLPool.pool(input.vertx(), input.msSQLConnectOptions(), input.poolOptions());
return MSSQLPool.pool(input.vertx(), input.msSQLConnectOptionsList(), input.poolOptions());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.reactive.mssql.client;

import java.util.List;

import io.quarkus.reactive.datasource.ReactiveDataSource;
import io.vertx.core.Vertx;
import io.vertx.mssqlclient.MSSQLConnectOptions;
Expand All @@ -25,6 +27,6 @@ interface Input {

PoolOptions poolOptions();

MSSQLConnectOptions msSQLConnectOptions();
List<MSSQLConnectOptions> msSQLConnectOptionsList();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For SQL Server, we should do the same as with Oracle (only log a warning if the user provides two or more urls).

}
}
Loading