You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ib...@apache.org on 2021/05/05 08:00:55 UTC

[ignite-3] branch main updated: IGNITE-14657 README.md for ignite-configuration module. (#109)

This is an automated email from the ASF dual-hosted git repository.

ibessonov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 592deed  IGNITE-14657 README.md for ignite-configuration module. (#109)
592deed is described below

commit 592deed3125354c5141c9d3793e4e06d78bcedcc
Author: ibessonov <be...@gmail.com>
AuthorDate: Wed May 5 11:00:48 2021 +0300

    IGNITE-14657 README.md for ignite-configuration module. (#109)
    
    Co-authored-by: Aleksandr Polovtsev <al...@gmail.com>
---
 .../configuration/processor/internal/Utils.java    |   4 +-
 modules/configuration/README.md                    | 163 +++++++++++++++++++++
 .../annotation/ConfigurationRoot.java              |   4 +-
 3 files changed, 167 insertions(+), 4 deletions(-)

diff --git a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/configuration/processor/internal/Utils.java b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/configuration/processor/internal/Utils.java
index c6312e0..aa221eb 100644
--- a/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/configuration/processor/internal/Utils.java
+++ b/modules/configuration-annotation-processor/src/main/java/org/apache/ignite/configuration/processor/internal/Utils.java
@@ -42,7 +42,7 @@ public class Utils {
     public static ClassName getConfigurationName(ClassName schemaClassName) {
         return ClassName.get(
             schemaClassName.packageName(),
-            schemaClassName.simpleName().replace("Schema", "Impl")
+            schemaClassName.simpleName().replaceAll("Schema$", "Impl")
         );
     }
 
@@ -55,7 +55,7 @@ public class Utils {
     public static ClassName getConfigurationInterfaceName(ClassName schemaClassName) {
         return ClassName.get(
             schemaClassName.packageName(),
-            schemaClassName.simpleName().replace("Schema", "")
+            schemaClassName.simpleName().replaceAll("Schema$", "")
         );
     }
 
diff --git a/modules/configuration/README.md b/modules/configuration/README.md
new file mode 100644
index 0000000..a332a4a
--- /dev/null
+++ b/modules/configuration/README.md
@@ -0,0 +1,163 @@
+# Configuration
+
+This module contains the API classes and the implementation for the Ignite Configuration framework.
+The idea is to provide the so-called _Unified Configuration_ — a common way of configuring both local Ignite nodes
+and remote Ignite clusters. The original concept is described in
+[IEP-55](https://cwiki.apache.org/confluence/display/IGNITE/IEP-55+Unified+Configuration).
+
+## Concepts
+
+### Configuration Schema
+
+Type-safe schema of a configuration, which is used for generating public API interfaces and
+internal implementations to avoid writing boilerplate code. 
+
+All schema classes must end with the `ConfigurationSchema` suffix.
+
+### Configuration Registry
+
+`ConfigurationRegistry` is the entry point of the module. It is used to register root keys, validators, storages and to
+start / stop the component. Refer to the class javadocs for more details.
+
+### Root Key
+
+All Ignite configuration instances can be represented by a forest, where every node has a name, usually referred
+to as a _key_. `RootKey` interface represents a type-safe object that holds the _key_ of the root node of the 
+configuration tree. 
+
+Instances of this interface are generated automatically and are mandatory for registering the configuration roots.
+
+### Example Schema
+
+An example configuration schema may look like the following:
+
+```java
+@ConfigurationRoot(rootName = "root", type = ConfigurationType.LOCAL)
+public static class ParentConfigurationSchema {
+    @NamedConfigValue
+    private NamedElementConfigurationSchema elements;
+
+    @ConfigValue
+    private ChildConfigurationSchema child;
+}
+
+@Config
+public static class ChildConfigurationSchema {
+    @Value(hasDefault = true)
+    public String str1 = "foobar";
+    
+    @Value
+    @Immutable
+    public String str2;
+}
+```
+
+* `@ConfigurationRoot` marks the root schema. It contains the following properties:
+  * `type` property, which can either be `LOCAL` or `DISTRIBUTED`. This property dictates the _storage_ type used 
+    to persist the schema — `Vault` or `Metastorage`. `Vault` stores data locally, while `Metastorage` is a distributed
+    system that should store only cluster-wide configuration properties;
+  * `rootName` property assigns a _key_ to the root node of the tree that will represent 
+    the corresponding configuration schema;
+* `@Config` is similar to the `@ConfigurationRoot` but represents an inner configuration node;
+* `@ConfigValue` marks a nested schema field. Cyclic dependencies are not allowed;
+* `@NamedConfigValue` is similar to `@ConfigValue`, but such fields represent a collection of properties, not a single
+  instance. Every element of the collection will have a `String` name, similar to a `Map`.
+  `NamedListConfiguration` interface is used to represent this field in the generated configuration classes. 
+* `@Value` annotation marks the _leaf_ values. `hasDefault` property can be used to set default values for fields:
+  if set to `true`, the default value will be used to initialize the annotated configuration field in case no value 
+  has been provided explicitly. This annotation can only be present on fields of the following types:
+  * `boolean` or `boolean[]`
+  * `int` or `int[]`
+  * `long` or `long[]`
+  * `double` or `double[]`
+  * `String` or `String[]`
+    
+  All _leaves_ must be public and corresponding configuration values **must not be null**;
+* `@Immutable` annotation can only be present on fields marked with the `@Value` annotation. Annotated fields cannot be 
+  changed after they have been initialized (either manually or by assigning a default value).
+
+## Generated API
+
+Configuration interfaces are generated at compile time. For the example above, the following code would be generated: 
+
+```java
+public interface ParentConfiguration extends ConfigurationTree<ParentView, ParentChange> {
+    RootKey<ParentConfiguration, ParentView> KEY = ...;
+
+    NamedConfigurationTree<NamedElementConfiguration, NamedElementView, NamedElementChange> elements();
+            
+    ChildConfiguration child();
+
+    ParentView value();
+
+    Future<Void> change(Consumer<ParentChange> change);
+}
+
+public interface ChildConfiguration extends ConfigurationTree<ChildView, ChildChange> {
+    ConfigurationValue<String> str();
+
+    ChildView value();
+
+    Future<Void> change(Consumer<ChildChange> change);
+}
+```
+
+* `KEY` constant uniquely identifies the configuration root;
+* `child()` method can be used to access the child node;
+* `value()` method creates a corresponding _snapshot_ (an immutable view) of the configuration node;
+* `change()` method should be used to update the values in the configuration tree.
+
+### Configuration Snapshots
+
+`value()` methods return a read-only view of the configuration tree, represented by a special set of _View_ interfaces.
+For the example above, the following interfaces would be generated:
+
+```java
+public interface ParentView {
+    NamedListView<? extends NamedElementView> elements();
+
+    ChildView child();
+}
+
+public interface ChildView {
+    String str();
+}
+```
+
+### Changing the configuration
+
+To modify the configuration tree, one should use the `change` method, which executes the update requests 
+asynchronously and in a transactional manner. Update requests are represented by a set of `Change` interfaces.
+For the example above, the following interfaces would be generated:
+
+```java
+public interface ParentChange {
+    ParentChange changeElements(Consumer<NamedListChange<NamedElementChange>> elements);
+
+    ParentChange changeChild(Consumer<ChildChange> child);
+}
+
+public interface ChildChange {
+    ChildChange changeStr(String str);
+}
+```
+
+For example, to update all child nodes of the parent configuration in a single transaction:
+
+```java
+ParentConfiguration parentCfg = ...;
+
+parentConfiguration.change(parent ->
+    parent.changeChild(child ->
+        child.changeStr("newStr1")
+    )
+).get();
+
+ChildConfiguration childCfg = parentCfg.child();
+
+childCfg.changeStr("newStr2").get();
+```
+
+It is possible to execute several change requests for different roots in a single transaction, but all these roots 
+_must have the same storage type_. However, this is only possible using the command line tool via the REST API, 
+there's no public Java API at the moment.
diff --git a/modules/configuration/src/main/java/org/apache/ignite/configuration/annotation/ConfigurationRoot.java b/modules/configuration/src/main/java/org/apache/ignite/configuration/annotation/ConfigurationRoot.java
index f897e0b..1658e76 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/configuration/annotation/ConfigurationRoot.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/configuration/annotation/ConfigurationRoot.java
@@ -23,7 +23,7 @@ import java.lang.annotation.Target;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 
 import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 /**
  * Annotation that marks underlying class as a root configuration schema. Has basically the same properties as
@@ -32,7 +32,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
  * @see Config
  */
 @Target(TYPE)
-@Retention(SOURCE)
+@Retention(RUNTIME)
 @Documented
 public @interface ConfigurationRoot {
     /** @return Unique root name. */