You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by mp...@apache.org on 2025/10/14 13:42:35 UTC
(ignite-3) branch IGNITE-26690 created (now 63f24ab7269)
This is an automated email from the ASF dual-hosted git repository.
mpochatkin pushed a change to branch IGNITE-26690
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
at 63f24ab7269 IGNITE-26690 Fix named list configuration updating
This branch includes the following new commits:
new 63f24ab7269 IGNITE-26690 Fix named list configuration updating
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(ignite-3) 01/01: IGNITE-26690 Fix named list configuration updating
Posted by mp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
mpochatkin pushed a commit to branch IGNITE-26690
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit 63f24ab7269d7e4b3618f45cd4f7b74cebb77bcb
Author: Mikhail Pochatkin <m....@gmail.com>
AuthorDate: Tue Oct 14 16:42:22 2025 +0300
IGNITE-26690 Fix named list configuration updating
---
.../storage/LocalFileConfigurationStorage.java | 80 ++++++++--------------
.../storage/LocalFileConfigurationStorageTest.java | 52 +++++++++++++-
2 files changed, 81 insertions(+), 51 deletions(-)
diff --git a/modules/configuration-storage/src/main/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorage.java b/modules/configuration-storage/src/main/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorage.java
index 081d19e3151..09ac65e5da2 100644
--- a/modules/configuration-storage/src/main/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorage.java
+++ b/modules/configuration-storage/src/main/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorage.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.configuration.storage;
import static java.util.Collections.emptyNavigableMap;
+import static java.util.concurrent.CompletableFuture.completedFuture;
import static java.util.stream.Collectors.toMap;
import static org.apache.ignite.internal.configuration.util.ConfigurationFlattener.createFlattenedUpdatesMap;
import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.fillFromPrefixMap;
@@ -29,9 +30,7 @@ import com.typesafe.config.Config;
import com.typesafe.config.ConfigException.Parse;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigObject;
-import com.typesafe.config.ConfigParseOptions;
import com.typesafe.config.ConfigRenderOptions;
-import com.typesafe.config.ConfigSyntax;
import com.typesafe.config.ConfigValue;
import com.typesafe.config.impl.ConfigImpl;
import java.io.IOException;
@@ -53,19 +52,19 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-import org.apache.ignite.configuration.ConfigurationDynamicDefaultsPatcher;
import org.apache.ignite.configuration.ConfigurationModule;
import org.apache.ignite.configuration.KeyIgnorer;
import org.apache.ignite.configuration.annotation.ConfigurationType;
import org.apache.ignite.configuration.validation.ConfigurationValidationException;
import org.apache.ignite.configuration.validation.ValidationIssue;
-import org.apache.ignite.internal.configuration.ConfigurationDynamicDefaultsPatcherImpl;
import org.apache.ignite.internal.configuration.ConfigurationTreeGenerator;
import org.apache.ignite.internal.configuration.NodeConfigCreateException;
import org.apache.ignite.internal.configuration.NodeConfigParseException;
import org.apache.ignite.internal.configuration.NodeConfigWriteException;
import org.apache.ignite.internal.configuration.SuperRoot;
+import org.apache.ignite.internal.configuration.SuperRootChangeImpl;
import org.apache.ignite.internal.configuration.hocon.HoconConverter;
+import org.apache.ignite.internal.configuration.tree.ConfigurationSource;
import org.apache.ignite.internal.configuration.tree.ConverterToMapVisitor;
import org.apache.ignite.internal.configuration.validation.ConfigurationDuplicatesValidator;
import org.apache.ignite.internal.future.InFlightFutures;
@@ -145,61 +144,52 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
checkAndRestoreConfigFile();
}
- /**
- * Patch the local configs with defaults from provided {@link ConfigurationModule}.
- *
- * @param hocon Config string in Hocon format.
- * @param module Configuration module, which provides configuration patches.
- * @return Patched config string in Hocon format.
- */
- private String patch(String hocon, ConfigurationModule module) {
- if (module == null) {
- return hocon;
- }
-
- ConfigurationDynamicDefaultsPatcher localCfgDynamicDefaultsPatcher = new ConfigurationDynamicDefaultsPatcherImpl(
- module,
- generator
- );
-
- return localCfgDynamicDefaultsPatcher.patchWithDynamicDefaults(hocon);
- }
-
@Override
public CompletableFuture<Data> readDataOnRecovery() {
lock.writeLock().lock();
try {
String hocon = readHoconFromFile();
- String hoconWithDynamicDefaults = patch(hocon, module);
+ SuperRoot superRoot = convertToSuperRoot(hocon);
+
+ Map<String, Serializable> transformedHocon = transformToMap(superRoot);
- transformToMap(hocon).forEach((key, value) -> {
+ transformedHocon.forEach((key, value) -> {
if (value != null) { // Filter defaults.
latest.put(key, value);
}
});
- return CompletableFuture.completedFuture(new Data(transformToMap(hoconWithDynamicDefaults), lastRevision));
+ module.patchConfigurationWithDynamicDefaults(new SuperRootChangeImpl(superRoot));
+ Map<String, Serializable> transformedHoconWithDefaults = transformToMap(superRoot);
+
+ return completedFuture(new Data(transformedHoconWithDefaults, lastRevision));
} finally {
lock.writeLock().unlock();
}
}
- private Map<String, Serializable> transformToMap(String hocon) {
- SuperRoot superRoot = generator.createSuperRoot();
- SuperRoot copiedSuperRoot = superRoot.copy();
+ private SuperRoot convertToSuperRoot(String hocon) {
+ try {
+ Config config = ConfigFactory.parseString(hocon);
+ KeyIgnorer keyIgnorer = module == null ? s -> false : KeyIgnorer.fromDeletedPrefixes(module.deletedPrefixes());
+
+ ConfigurationSource hoconSource = HoconConverter.hoconSource(config.root(), keyIgnorer);
- KeyIgnorer keyIgnorer = module == null ? s -> false : KeyIgnorer.fromDeletedPrefixes(module.deletedPrefixes());
+ SuperRoot superRoot = generator.createSuperRoot();
+ hoconSource.descend(superRoot);
- HoconConverter.hoconSource(parseConfig(hocon).root(), keyIgnorer).descend(copiedSuperRoot);
+ return superRoot;
+ } catch (Exception e) {
+ throw new ConfigurationValidationException("Failed to parse HOCON: " + e.getMessage());
+ }
+ }
- return createFlattenedUpdatesMap(superRoot, copiedSuperRoot, emptyNavigableMap())
+ private Map<String, Serializable> transformToMap(SuperRoot superRoot) {
+ return createFlattenedUpdatesMap(generator.createSuperRoot(), superRoot, emptyNavigableMap())
.entrySet()
.stream()
.filter(e -> e.getValue() != null)
- .collect(toMap(
- Entry::getKey,
- Entry::getValue)
- );
+ .collect(toMap(Entry::getKey, Entry::getValue));
}
private String readHoconFromFile() {
@@ -220,21 +210,11 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
}
}
- private Config parseConfig(String confString) {
- try {
- ConfigParseOptions parseOptions = ConfigParseOptions.defaults().setSyntax(ConfigSyntax.CONF).setAllowMissing(false);
-
- return ConfigFactory.parseString(confString, parseOptions);
- } catch (Parse e) {
- throw new NodeConfigParseException("Failed to parse config content from file " + configPath, e);
- }
- }
-
@Override
public CompletableFuture<Map<String, ? extends Serializable>> readAllLatest(String prefix) {
lock.readLock().lock();
try {
- return CompletableFuture.completedFuture(
+ return completedFuture(
latest.entrySet()
.stream()
.filter(entry -> entry.getKey().startsWith(prefix))
@@ -249,7 +229,7 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
public CompletableFuture<Serializable> readLatest(String key) {
lock.readLock().lock();
try {
- return CompletableFuture.completedFuture(latest.get(key));
+ return completedFuture(latest.get(key));
} finally {
lock.readLock().unlock();
}
@@ -303,7 +283,7 @@ public class LocalFileConfigurationStorage implements ConfigurationStorage {
@Override
public CompletableFuture<Long> lastRevision() {
- return CompletableFuture.completedFuture(lastRevision);
+ return completedFuture(lastRevision);
}
@Override
diff --git a/modules/configuration-storage/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java b/modules/configuration-storage/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
index c78382a5033..96b759c1678 100644
--- a/modules/configuration-storage/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
+++ b/modules/configuration-storage/src/test/java/org/apache/ignite/internal/configuration/storage/LocalFileConfigurationStorageTest.java
@@ -50,12 +50,18 @@ import org.apache.ignite.configuration.KeyIgnorer;
import org.apache.ignite.configuration.annotation.Config;
import org.apache.ignite.configuration.annotation.ConfigValue;
import org.apache.ignite.configuration.annotation.ConfigurationRoot;
+import org.apache.ignite.configuration.annotation.InjectedName;
import org.apache.ignite.configuration.annotation.NamedConfigValue;
+import org.apache.ignite.configuration.annotation.PolymorphicConfig;
+import org.apache.ignite.configuration.annotation.PolymorphicConfigInstance;
+import org.apache.ignite.configuration.annotation.PolymorphicId;
import org.apache.ignite.configuration.annotation.PublicName;
import org.apache.ignite.configuration.annotation.Value;
import org.apache.ignite.configuration.validation.ConfigurationValidationException;
import org.apache.ignite.internal.configuration.ConfigurationTreeGenerator;
import org.apache.ignite.internal.configuration.TestConfigurationChanger;
+import org.apache.ignite.internal.configuration.hocon.HoconConverter;
+import org.apache.ignite.internal.configuration.tree.ConfigurationSource;
import org.apache.ignite.internal.configuration.validation.ConfigurationValidatorImpl;
import org.apache.ignite.internal.testframework.WorkDirectory;
import org.apache.ignite.internal.testframework.WorkDirectoryExtension;
@@ -85,7 +91,11 @@ public class LocalFileConfigurationStorageTest {
@BeforeAll
public static void beforeAll() {
- treeGenerator = new ConfigurationTreeGenerator(TopConfiguration.KEY, TopEmptyConfiguration.KEY);
+ treeGenerator = new ConfigurationTreeGenerator(
+ List.of(TopConfiguration.KEY, TopEmptyConfiguration.KEY),
+ List.of(),
+ List.of(FirstNamedListConfigurationSchema.class)
+ );
}
@AfterAll
@@ -545,6 +555,28 @@ public class LocalFileConfigurationStorageTest {
assertThat(storage.write(Map.of(), storage.localRevision().get() + 1), willCompleteSuccessfully());
}
+ @Test
+ void updateAfterRestart() throws Exception {
+ assertThat(configFileContent(), emptyString());
+
+ // Initialize value
+ com.typesafe.config.Config config = ConfigFactory.parseString("top.polyNamedList = [{name=name1,strVal=foo,type=first}]");
+ ConfigurationSource source = HoconConverter.hoconSource(config.root());
+
+ changer.start();
+ changer.change(source).join();
+
+ // Force restart of the storage
+ after();
+ before();
+
+ config = ConfigFactory.parseString("top.polyNamedList.name1.strVal=strVal1");
+ source = HoconConverter.hoconSource(config.root());
+
+ changer.start();
+ changer.change(source).join();
+ }
+
private String configFileContent() throws IOException {
return Files.readString(getConfigFile());
}
@@ -569,6 +601,9 @@ public class LocalFileConfigurationStorageTest {
@Deprecated
@Value(hasDefault = true)
public int deprecated = 0;
+
+ @NamedConfigValue
+ public PolyNamedListConfigurationSchema polyNamedList;
}
@@ -601,4 +636,19 @@ public class LocalFileConfigurationStorageTest {
@Value(hasDefault = true)
public int intVal = 1;
}
+
+ @PolymorphicConfig
+ public static class PolyNamedListConfigurationSchema {
+ @PolymorphicId
+ public String type;
+
+ @InjectedName
+ public String name;
+ }
+
+ @PolymorphicConfigInstance("first")
+ public static class FirstNamedListConfigurationSchema extends PolyNamedListConfigurationSchema {
+ @Value(hasDefault = true)
+ public String strVal = "foo";
+ }
}