Skip to content

Commit

Permalink
RuntimeConfigDefault changes ignored on restart
Browse files Browse the repository at this point in the history
Fixes #17069
  • Loading branch information
stuartwdouglas committed Jul 28, 2021
1 parent 6ff45d3 commit f159dec
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ private RunTimeConfigurationGenerator() {
}

public static final class GenerateOperation implements AutoCloseable {
final boolean devMode;
final LaunchMode launchMode;
final AccessorFinder accessorFinder;
final ClassOutput classOutput;
Expand All @@ -281,8 +280,6 @@ public static final class GenerateOperation implements AutoCloseable {
// default values given in the build configuration
final Map<String, String> specifiedRunTimeDefaultValues;
final Map<String, String> buildTimeRunTimeVisibleValues;
// default values produced by extensions via build item
final Map<String, String> runTimeDefaults;
final Map<Container, MethodDescriptor> enclosingMemberMethods = new HashMap<>();
final Map<Class<?>, MethodDescriptor> groupInitMethods = new HashMap<>();
final Map<Class<?>, FieldDescriptor> configRootsByType = new HashMap<>();
Expand Down Expand Up @@ -315,7 +312,6 @@ public static final class GenerateOperation implements AutoCloseable {

GenerateOperation(Builder builder) {
this.launchMode = builder.launchMode;
this.devMode = builder.launchMode == LaunchMode.DEVELOPMENT;
final BuildTimeConfigurationReader.ReadResult buildTimeReadResult = builder.buildTimeReadResult;
buildTimeConfigResult = Assert.checkNotNullParam("buildTimeReadResult", buildTimeReadResult);
specifiedRunTimeDefaultValues = Assert.checkNotNullParam("specifiedRunTimeDefaultValues",
Expand All @@ -324,7 +320,6 @@ public static final class GenerateOperation implements AutoCloseable {
buildTimeReadResult.getBuildTimeRunTimeVisibleValues());
classOutput = Assert.checkNotNullParam("classOutput", builder.getClassOutput());
roots = Assert.checkNotNullParam("builder.roots", builder.getBuildTimeReadResult().getAllRoots());
runTimeDefaults = Assert.checkNotNullParam("runTimeDefaults", builder.getRunTimeDefaults());
additionalTypes = Assert.checkNotNullParam("additionalTypes", builder.getAdditionalTypes());
additionalBootstrapConfigSourceProviders = builder.getAdditionalBootstrapConfigSourceProviders();
staticConfigSources = builder.getStaticConfigSources();
Expand All @@ -341,7 +336,7 @@ public static final class GenerateOperation implements AutoCloseable {
mc.invokeSpecialMethod(MethodDescriptor.ofConstructor(Object.class), mc.getThis());
mc.returnValue(null);
}
if (devMode) {
if (launchMode.isDevOrTest()) {
reinit = cc.getMethodCreator(REINIT);
reinit.setModifiers(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC);
} else {
Expand Down Expand Up @@ -458,7 +453,7 @@ public void run() {
// make the build time config global until we read the run time config -
// at run time (when we're ready) we update the factory and then release the build time config
installConfiguration(clinitConfig, clinit);
if (devMode) {
if (launchMode.isDevOrTest()) {
final ResultHandle buildTimeRunTimeDefaultValuesConfigSource = reinit
.readStaticField(C_BUILD_TIME_RUN_TIME_DEFAULTS_CONFIG_SOURCE);
// create the map for build time config source
Expand Down Expand Up @@ -536,28 +531,21 @@ public void run() {
readConfig.invokeStaticMethod(CU_ADD_SOURCE_PROVIDER, runTimeBuilder, readConfig.newInstance(
MethodDescriptor.ofConstructor("io.quarkus.runtime.generated.ConfigSourceProviderImpl")));

// create the map for run time specified values config source
final ResultHandle specifiedRunTimeValues = clinit.newInstance(HM_NEW);
if (!devMode) {
//we don't need these in devmode
if (!launchMode.isDevOrTest()) {
// create the map for run time specified values config source
//we don't need these in dev/test mode
//including it would just cache the first values
//but these can already just be read directly, as we are in the same JVM
for (Map.Entry<String, String> entry : specifiedRunTimeDefaultValues.entrySet()) {
clinit.invokeVirtualMethod(HM_PUT, specifiedRunTimeValues, clinit.load(entry.getKey()),
clinit.load(entry.getValue()));
}
}
for (Map.Entry<String, String> entry : runTimeDefaults.entrySet()) {
if (!specifiedRunTimeDefaultValues.containsKey(entry.getKey())) {
// only add entry if the user didn't override it
clinit.invokeVirtualMethod(HM_PUT, specifiedRunTimeValues, clinit.load(entry.getKey()),
clinit.load(entry.getValue()));
}
}
final ResultHandle specifiedRunTimeSource = clinit.newInstance(PCS_NEW, specifiedRunTimeValues,
clinit.load("Specified default values"), clinit.load(Integer.MIN_VALUE + 100));
cc.getFieldCreator(C_SPECIFIED_RUN_TIME_CONFIG_SOURCE)
.setModifiers(Opcodes.ACC_STATIC | (devMode ? Opcodes.ACC_VOLATILE : Opcodes.ACC_FINAL));
.setModifiers(Opcodes.ACC_STATIC | Opcodes.ACC_FINAL);
clinit.writeStaticField(C_SPECIFIED_RUN_TIME_CONFIG_SOURCE, specifiedRunTimeSource);

// add in the custom sources that bootstrap config needs
Expand Down Expand Up @@ -704,7 +692,7 @@ public void run() {
// config root field is volatile in dev mode, final otherwise; we initialize it from clinit, and readConfig in dev mode
cc.getFieldCreator(rootFieldDescriptor)
.setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC
| (devMode ? Opcodes.ACC_VOLATILE : Opcodes.ACC_FINAL));
| (launchMode.isDevOrTest() ? Opcodes.ACC_VOLATILE : Opcodes.ACC_FINAL));

// construct instance in <clinit>
ResultHandle instance;
Expand All @@ -724,7 +712,7 @@ public void run() {
}
clinit.invokeStaticMethod(initGroup, clinitConfig, clinitNameBuilder, instance);
clinit.invokeVirtualMethod(SB_SET_LENGTH, clinitNameBuilder, clInitOldLen);
if (devMode) {
if (launchMode.isDevOrTest()) {
instance = readConfig.readStaticField(rootFieldDescriptor);
if (!rootName.isEmpty()) {
readConfig.invokeVirtualMethod(SB_APPEND_CHAR, readConfigNameBuilder, readConfig.load('.'));
Expand Down Expand Up @@ -794,7 +782,7 @@ public void run() {
clinit.invokeStaticMethod(CD_UNKNOWN_PROPERTIES,
clinit.readStaticField(FieldDescriptor.of(cc.getClassName(), "unused", List.class)));

if (devMode) {
if (launchMode.isDevOrTest()) {
configSweepLoop(siParserBody, readConfig, runTimeConfig);
}
// generate sweep for run time
Expand Down Expand Up @@ -1672,7 +1660,6 @@ public static final class Builder {
private LaunchMode launchMode;
private ClassOutput classOutput;
private BuildTimeConfigurationReader.ReadResult buildTimeReadResult;
private Map<String, String> runTimeDefaults;
private List<Class<?>> additionalTypes;
private List<String> additionalBootstrapConfigSourceProviders;

Expand Down Expand Up @@ -1704,15 +1691,6 @@ public Builder setBuildTimeReadResult(final BuildTimeConfigurationReader.ReadRes
return this;
}

Map<String, String> getRunTimeDefaults() {
return runTimeDefaults;
}

public Builder setRunTimeDefaults(final Map<String, String> runTimeDefaults) {
this.runTimeDefaults = runTimeDefaults;
return this;
}

List<Class<?>> getAdditionalTypes() {
return additionalTypes;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
import io.quarkus.deployment.builditem.LiveReloadBuildItem;
import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem;
import io.quarkus.deployment.builditem.RunTimeConfigurationSourceValueBuildItem;
import io.quarkus.deployment.builditem.StaticInitConfigSourceFactoryBuildItem;
import io.quarkus.deployment.builditem.StaticInitConfigSourceProviderBuildItem;
import io.quarkus.deployment.builditem.SuppressNonRuntimeConfigChangedWarningBuildItem;
Expand All @@ -48,7 +49,7 @@
import io.quarkus.gizmo.ClassOutput;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.StaticInitSafe;
import io.quarkus.runtime.configuration.ConfigChangeRecorder;
import io.quarkus.runtime.configuration.ConfigRecorder;
import io.quarkus.runtime.configuration.ConfigurationRuntimeConfig;
import io.quarkus.runtime.configuration.RuntimeOverrideConfigSource;
import io.smallrye.config.ConfigSourceFactory;
Expand All @@ -74,13 +75,24 @@ void staticInitSources(
PropertiesLocationConfigSourceFactory.class.getName()));
}

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
RunTimeConfigurationSourceValueBuildItem devTestConfig(List<RunTimeConfigurationDefaultBuildItem> runTimeDefaults,
ConfigRecorder recorder) {
if (runTimeDefaults.isEmpty()) {
return null;
}
return new RunTimeConfigurationSourceValueBuildItem(recorder.config(runTimeDefaults.stream().collect(
Collectors.toMap(RunTimeConfigurationDefaultBuildItem::getKey, RunTimeConfigurationDefaultBuildItem::getValue)),
Integer.MIN_VALUE + 50));
}

/**
* Generate the Config class that instantiates MP Config and holds all the config objects
*/
@BuildStep
void generateConfigClass(
ConfigurationBuildItem configItem,
List<RunTimeConfigurationDefaultBuildItem> runTimeDefaults,
List<ConfigurationTypeBuildItem> typeItems,
LaunchModeBuildItem launchModeBuildItem,
BuildProducer<GeneratedClassBuildItem> generatedClass,
Expand All @@ -95,13 +107,6 @@ void generateConfigClass(
return;
}

Map<String, String> defaults = new HashMap<>();
for (RunTimeConfigurationDefaultBuildItem item : runTimeDefaults) {
if (defaults.putIfAbsent(item.getKey(), item.getValue()) != null) {
throw new IllegalStateException("More than one default value for " + item.getKey() + " was produced");
}
}

Set<String> discoveredConfigSources = discoverService(ConfigSource.class, reflectiveClass);
Set<String> discoveredConfigSourceProviders = discoverService(ConfigSourceProvider.class, reflectiveClass);
Set<String> discoveredConfigSourceFactories = discoverService(ConfigSourceFactory.class, reflectiveClass);
Expand All @@ -120,7 +125,6 @@ void generateConfigClass(
.setBuildTimeReadResult(configItem.getReadResult())
.setClassOutput(new GeneratedClassGizmoAdaptor(generatedClass, false))
.setLaunchMode(launchModeBuildItem.getLaunchMode())
.setRunTimeDefaults(defaults)
.setAdditionalTypes(typeItems.stream().map(ConfigurationTypeBuildItem::getValueType).collect(toList()))
.setAdditionalBootstrapConfigSourceProviders(
getAdditionalBootstrapConfigSourceProviders(additionalBootstrapConfigSourceProviders))
Expand Down Expand Up @@ -157,7 +161,7 @@ public SuppressNonRuntimeConfigChangedWarningBuildItem ignoreQuarkusProfileChang
@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
public void checkForBuildTimeConfigChange(
ConfigChangeRecorder recorder, ConfigurationBuildItem configItem, LoggingSetupBuildItem loggingSetupBuildItem,
ConfigRecorder recorder, ConfigurationBuildItem configItem, LoggingSetupBuildItem loggingSetupBuildItem,
ConfigurationRuntimeConfig configurationConfig,
List<SuppressNonRuntimeConfigChangedWarningBuildItem> suppressNonRuntimeConfigChangedWarningItems) {
BuildTimeConfigurationReader.ReadResult readResult = configItem.getReadResult();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
package io.quarkus.runtime.configuration;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.spi.ConfigSource;
import org.eclipse.microprofile.config.spi.ConfigSourceProvider;
import org.jboss.logging.Logger;

import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.annotations.Recorder;
import io.quarkus.runtime.configuration.ConfigurationRuntimeConfig.BuildTimeMismatchAtRuntime;
import io.smallrye.config.common.MapBackedConfigSource;

@Recorder
public class ConfigChangeRecorder {
public class ConfigRecorder {

private static final Logger log = Logger.getLogger(ConfigChangeRecorder.class);
private static final Logger log = Logger.getLogger(ConfigRecorder.class);

public void handleConfigChange(ConfigurationRuntimeConfig configurationConfig, Map<String, String> buildTimeConfig) {
Config configProvider = ConfigProvider.getConfig();
Expand Down Expand Up @@ -50,4 +55,14 @@ public void handleConfigChange(ConfigurationRuntimeConfig configurationConfig, M

}
}

public RuntimeValue<ConfigSourceProvider> config(Map<String, String> values, int priority) {
return new RuntimeValue<>(new ConfigSourceProvider() {
@Override
public Iterable<ConfigSource> getConfigSources(ClassLoader forClassLoader) {
return Collections.singleton(new MapBackedConfigSource("Runtime Default Values", values, priority) {
});
}
});
}
}

0 comments on commit f159dec

Please sign in to comment.