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 all commits
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
18 changes: 14 additions & 4 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@
<microprofile-lra.version>2.0</microprofile-lra.version>
<microprofile-openapi.version>3.1</microprofile-openapi.version>
<smallrye-common.version>2.1.0</smallrye-common.version>
<smallrye-config.version>3.1.3</smallrye-config.version>
<smallrye-config.version>3.2.0</smallrye-config.version>
<smallrye-health.version>4.0.1</smallrye-health.version>
<smallrye-metrics.version>4.0.0</smallrye-metrics.version>
<smallrye-open-api.version>3.3.0</smallrye-open-api.version>
<smallrye-open-api.version>3.3.1</smallrye-open-api.version>
<smallrye-graphql.version>2.1.2</smallrye-graphql.version>
<smallrye-opentracing.version>3.0.3</smallrye-opentracing.version>
<smallrye-fault-tolerance.version>6.2.1</smallrye-fault-tolerance.version>
Expand Down Expand Up @@ -128,7 +128,7 @@
<quartz.version>2.3.2</quartz.version>
<h2.version>2.1.214</h2.version> <!-- When updating, needs to be matched in io.quarkus.hibernate.orm.runtime.config.DialectVersions -->
<postgresql-jdbc.version>42.6.0</postgresql-jdbc.version>
<mariadb-jdbc.version>3.1.2</mariadb-jdbc.version>
<mariadb-jdbc.version>3.1.3</mariadb-jdbc.version>
<mysql-jdbc.version>8.0.30</mysql-jdbc.version>
<mssql-jdbc.version>12.2.0.jre11</mssql-jdbc.version>
<adal4j.version>1.6.7</adal4j.version>
Expand Down Expand Up @@ -3809,6 +3809,11 @@
<artifactId>smallrye-config-common</artifactId>
<version>${smallrye-config.version}</version>
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config-core</artifactId>
<version>${smallrye-config.version}</version>
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config-validator</artifactId>
Expand All @@ -3826,7 +3831,12 @@
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config-core</artifactId>
<artifactId>smallrye-config-source-keystore</artifactId>
<version>${smallrye-config.version}</version>
</dependency>
<dependency>
<groupId>io.smallrye.config</groupId>
<artifactId>smallrye-config-crypto</artifactId>
<version>${smallrye-config.version}</version>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
import org.jboss.logging.Logger;

import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
Expand All @@ -38,6 +37,7 @@
import io.quarkus.paths.PathCollection;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.util.JavaVersionUtil;
import io.smallrye.config.SmallRyeConfigProviderResolver;

public class QuarkusAugmentor {

Expand Down Expand Up @@ -177,8 +177,8 @@ public BuildResult run() throws Exception {
return buildResult;
} finally {
try {
ConfigProviderResolver.instance()
.releaseConfig(ConfigProviderResolver.instance().getConfig(deploymentClassLoader));
((SmallRyeConfigProviderResolver) SmallRyeConfigProviderResolver.instance())
.releaseConfig(deploymentClassLoader);
} catch (Exception ignore) {

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import io.smallrye.config.ConfigSourceInterceptor;
import io.smallrye.config.ConfigSourceInterceptorFactory;
import io.smallrye.config.ConfigValidator;
import io.smallrye.config.SecretKeysHandler;
import io.smallrye.config.SecretKeysHandlerFactory;
import io.smallrye.config.SmallRyeConfigProviderResolver;

class ConfigBuildSteps {
Expand Down Expand Up @@ -90,6 +92,8 @@ void nativeServiceProviders(
Converter.class,
ConfigSourceInterceptor.class,
ConfigSourceInterceptorFactory.class,
SecretKeysHandler.class,
SecretKeysHandlerFactory.class,
ConfigValidator.class)) {
final String serviceName = serviceClass.getName();
final Set<String> names = ServiceUtil.classNamesNamedIn(classLoader, SERVICES_PREFIX + serviceName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,8 @@ public static SmallRyeConfigBuilder configBuilder(final boolean runTime, final b
final boolean addDiscovered, final LaunchMode launchMode) {
SmallRyeConfigBuilder builder = emptyConfigBuilder();

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
builder.forClassLoader(classLoader);
builder.addDefaultSources();
builder.withSources(new ApplicationPropertiesConfigSourceLoader.InFileSystem());
builder.withSources(new ApplicationPropertiesConfigSourceLoader.InClassPath());
builder.withSources(new DotEnvConfigSourceProvider());
if (launchMode.isDevOrTest() && (runTime || bootstrap)) {
builder.withSources(new RuntimeOverrideConfigSource(classLoader));
builder.withSources(new RuntimeOverrideConfigSource(Thread.currentThread().getContextClassLoader()));
}
if (runTime || bootstrap) {
// Validator only for runtime. We cannot use the current validator for build time (chicken / egg problem)
Expand Down Expand Up @@ -184,9 +178,16 @@ public OptionalInt getPriority() {
// Ignore unmapped quarkus properties, because properties in the same root may be split between build / runtime
builder.withMappingIgnore("quarkus.**");

builder.addDefaultInterceptors();
builder.addDiscoveredInterceptors();
builder.addDiscoveredConverters();
builder.forClassLoader(Thread.currentThread().getContextClassLoader())
.addDiscoveredConverters()
.addDefaultInterceptors()
.addDiscoveredInterceptors()
.addDiscoveredSecretKeysHandlers()
.addDefaultSources()
.withSources(new ApplicationPropertiesConfigSourceLoader.InFileSystem())
.withSources(new ApplicationPropertiesConfigSourceLoader.InClassPath())
.withSources(new DotEnvConfigSourceProvider());

return builder;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public SmallRyeConfig getConfigFor(final SmallRyeConfigProviderResolver configPr
//TODO: this code path is only hit when start fails in dev mode very early in the process
//the recovery code will fail without this as it cannot read any properties such as
//the HTTP port or logging info
return ConfigUtils.emptyConfigBuilder().addDefaultSources().addDiscoveredSources().build();
return ConfigUtils.emptyConfigBuilder().addDiscoveredSources().build();
}
return config;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import org.junit.jupiter.api.Test;

import io.smallrye.config.ExpressionConfigSourceInterceptor;
import io.smallrye.config.PropertiesConfigSource;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;
Expand All @@ -20,11 +19,10 @@
public class ConfigExpanderTestCase {

private SmallRyeConfig buildConfig(Map<String, String> configMap) {
final SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder();
builder.withInterceptors(new ExpressionConfigSourceInterceptor());
builder.withSources(new PropertiesConfigSource(configMap, "test input", 500));
final SmallRyeConfig config = (SmallRyeConfig) builder.build();
return config;
return new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.withSources(new PropertiesConfigSource(configMap, "test input", 500))
.build();
}

private Map<String, String> maps(Map... maps) {
Expand Down
87 changes: 76 additions & 11 deletions docs/src/main/asciidoc/config-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -394,10 +394,58 @@ Then

[WARNING]
====
The configuration `quarkus.config.profile.parent` must be placed in the main `application.properties` file, passed as a system property, or passed as an environment variable.
It does not work when the configuration is placed in the profile aware files.
Do not use Profile aware files to set `quarkus.config.profile.parent`. This will not work because the profile is
required in advance to load the profile aware files.
====

=== Multiple Profiles

Multiple Profiles may be active at the same time. The configuration `quarkus.profile` accepts a comma-separated list
of profile names: `quarkus.profile=common,dev`. Both `common` and `dev` are separate profiles.

When multiple profiles are active, the rules for profile configuration are the same. If two profiles define the same
configuration, then the last listed profile has priority. Consider:

.application.properties
[source,properties]
----
quarkus.profile=common,dev

my.prop=1234
%common.my.prop=1234
%dev.my.prop=5678

%common.commom.prop=common
%dev.dev.prop=dev
%test.test.prop=test
----

Then

* `common.prop` value is `common`
* `dev.prop` value is `dev`
* `my.prop` value is `5678`
* `test.prop` does not have a `value`

It is also possible to define multiple profile properties, with a comma-separated list of profile names. If the same
property name exists in multiple profile properties then, the property name with the most specific profile wins:

.application.properties
[source,properties]
----
quarkus.profile=dev

%prod,dev.my.prop=1234
%dev.my.prop=5678

%prod,dev.another.prop=1234
----

Then

* `my.prop` value is 5678.
* `another.prop` value is 1234.

=== Default Runtime Profile

The default Quarkus runtime profile is set to the profile used to build the application:
Expand Down Expand Up @@ -475,6 +523,23 @@ application.host=${HOST:${remote.host}}
This will expand the `HOST` environment variable and use the value of the property `remote.host` as the default value
if `HOST` is not set.

== Secret Keys Expressions

A secret configuration may be expressed as `${handler::value}`, where the `handler` is the name of a
`io.smallrye.config.SecretKeysHandler` to decode or decrypt the `value`. Consider:

.application.properties
[source,properties]
----
my.secret=${aes-gcm-nopadding::DJNrZ6LfpupFv6QbXyXhvzD8eVDnDa_kTliQBpuzTobDZxlg}
----

A lookup to `my.secret` will use the `SecretKeysHandler` name `aes-gcm-nopadding` to decode the value
`DJNrZ6LfpupFv6QbXyXhvzD8eVDnDa_kTliQBpuzTobDZxlg`.

For more information, please check SmallRye Config
link:https://smallrye.io/smallrye-config/Main/config/secret-keys/[Secret Keys] documentation.

== Accessing a generating UUID

The default config source from Quarkus provides a random UUID value.
Expand Down Expand Up @@ -568,23 +633,23 @@ If you are in the rare situation that you need to change the build time configur
== Additional Information

* xref:config-yaml.adoc[YAML ConfigSource Extension]
// Moved to Quarkiverse. There is a redirect to resolve the link
* xref:vault.adoc[HashiCorp Vault ConfigSource Extension]
// Moved to Quarkiverse. There is a redirect to resolve the link
* xref:consul-config.adoc[Consul ConfigSource Extension]
* xref:spring-cloud-config-client.adoc[Spring Cloud ConfigSource Extension]
* xref:config-mappings.adoc[Mapping configuration to objects]
* xref:config-extending-support.adoc[Extending configuration support]

Quarkus relies on link:https://github.com/smallrye/smallrye-config/[SmallRye Config] and inherits its features:

* Additional ``ConfigSource``s
* Additional ``Converter``s
* Indexed properties
* Parent profile
* Interceptors for configuration value resolution
* Relocate configuration properties
* Fallback configuration properties
* Logging
* Hide secrets
* link:https://smallrye.io/smallrye-config/Main/config-sources/custom/[Additional Config Sources]
* link:https://smallrye.io/smallrye-config/Main/config-sources/factories/[Config Source Factories]
* link:https://smallrye.io/smallrye-config/Main/converters/custom/[Additional Converters]
* link:https://smallrye.io/smallrye-config/Main/extensions/interceptors/[Interceptors]
* link:https://smallrye.io/smallrye-config/Main/extensions/relocate/[Relocate Configuration]
* link:https://smallrye.io/smallrye-config/Main/extensions/fallback/[Fallback Configuration]
* link:https://smallrye.io/smallrye-config/Main/config/secret-keys/[Secret Keys]

For more information, please check the
link:https://smallrye.io/smallrye-config/Main[SmallRye Config documentation].
Expand Down
14 changes: 9 additions & 5 deletions docs/src/main/asciidoc/opentelemetry.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,26 @@ endpoint will be traced without any required code changes.

=== Create the configuration

There are no mandatory configurations for the extension to work. If you need to change any of the default property values, here is an example on how to configure the default OTLP gRPC Exporter within the application, using the `src/main/resources/application.properties` file:
There are no mandatory configurations for the extension to work.

If you need to change any of the default property values, here is an example on how to configure the default OTLP gRPC Exporter within the application, using the `src/main/resources/application.properties` file:

[source,properties]
----
quarkus.application.name=myservice // <1>
quarkus.otel.exporter.otlp.traces.endpoint=http://localhost:4317 // <2>
quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{traceId}, parentId=%X{parentId}, spanId=%X{spanId}, sampled=%X{sampled} [%c{2.}] (%t) %s%e%n // <3>
quarkus.otel.exporter.otlp.traces.headers=authorization=Bearer my_secret // <3>
quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{traceId}, parentId=%X{parentId}, spanId=%X{spanId}, sampled=%X{sampled} [%c{2.}] (%t) %s%e%n // <4>

# Alternative to the console log
quarkus.http.access-log.pattern="...traceId=%{X,traceId} spanId=%{X,spanId}" // <4>
quarkus.http.access-log.pattern="...traceId=%{X,traceId} spanId=%{X,spanId}" // <5>
----

<1> All spans created from the application will include an OpenTelemetry `Resource` indicating the span was created by the `myservice` application. If not set, it will default to the artifact id.
<2> gRPC endpoint to send spans. If not set, it will default to `http://localhost:4317`.
<3> Add tracing information into log messages.
<4> You can also only put the trace info into the access log. In this case you must omit the info in the console log format.
<3> Optional gRPC headers commonly used for authentication
<4> Add tracing information into log messages.
<5> You can also only put the trace info into the access log. In this case you must omit the info in the console log format.

[NOTE]
====
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* the same as Hibernate ORM's default one except it records the dialect
* so that we can reuse it at runtime init.
*/
public final class QuarkusStaticInitDialectFactory extends DialectFactoryImpl
public class QuarkusStaticInitDialectFactory extends DialectFactoryImpl
implements DialectFactory, ServiceRegistryAwareService {

private Dialect dialect;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
import io.quarkus.hibernate.orm.runtime.service.QuarkusImportSqlCommandExtractorInitiator;
import io.quarkus.hibernate.orm.runtime.service.QuarkusMutableIdentifierGeneratorFactoryInitiator;
import io.quarkus.hibernate.orm.runtime.service.QuarkusRegionFactoryInitiator;
import io.quarkus.hibernate.orm.runtime.service.QuarkusStaticInitDialectFactoryInitiator;
import io.quarkus.hibernate.orm.runtime.service.StandardHibernateORMInitiatorListProvider;
import io.quarkus.hibernate.reactive.runtime.customized.QuarkusNoJdbcConnectionProviderInitiator;
import io.quarkus.hibernate.reactive.runtime.customized.QuarkusReactiveDialectFactoryInitiator;

/**
* Defines the initial list of StandardServiceInitiator instances used to initialize the
Expand Down Expand Up @@ -86,8 +86,8 @@ public List<StandardServiceInitiator<?>> initialInitiatorList() {
serviceInitiators.add(MultiTenantConnectionProviderInitiator.INSTANCE);
serviceInitiators.add(DialectResolverInitiator.INSTANCE);

// Custom Quarkus implementation !
serviceInitiators.add(QuarkusStaticInitDialectFactoryInitiator.INSTANCE);
// Custom Quarkus V Reactive implementation !
serviceInitiators.add(QuarkusReactiveDialectFactoryInitiator.INSTANCE);

// Default implementation
serviceInitiators.add(BatchBuilderInitiator.INSTANCE);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.quarkus.hibernate.reactive.runtime.customized;

import java.util.Map;

import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.engine.jdbc.dialect.spi.DialectFactory;
import org.hibernate.service.spi.ServiceRegistryImplementor;

public final class QuarkusReactiveDialectFactoryInitiator implements StandardServiceInitiator<DialectFactory> {

public static final QuarkusReactiveDialectFactoryInitiator INSTANCE = new QuarkusReactiveDialectFactoryInitiator();

@Override
public Class<DialectFactory> getServiceInitiated() {
return DialectFactory.class;
}

@Override
public DialectFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
return new ReactiveQuarkusStaticInitDialectFactory();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkus.hibernate.reactive.runtime.customized;

import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectFactory;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoSource;
import org.hibernate.reactive.dialect.ReactiveDialectWrapper;
import org.hibernate.service.spi.ServiceRegistryAwareService;

import io.quarkus.hibernate.orm.runtime.service.QuarkusStaticInitDialectFactory;

public class ReactiveQuarkusStaticInitDialectFactory extends QuarkusStaticInitDialectFactory
implements DialectFactory, ServiceRegistryAwareService {

private Dialect wrapDialect;

@Override
public Dialect buildDialect(Map<String, Object> map, DialectResolutionInfoSource dialectResolutionInfoSource)
throws HibernateException {
this.wrapDialect = new ReactiveDialectWrapper(super.buildDialect(map, dialectResolutionInfoSource));
return this.wrapDialect;
}

@Override
public Dialect getDialect() {
return this.wrapDialect;
}
}
Loading