Ivan Bessonov created IGNITE-25048:
--------------------------------------

             Summary: Support configuration deprecation
                 Key: IGNITE-25048
                 URL: https://issues.apache.org/jira/browse/IGNITE-25048
             Project: Ignite
          Issue Type: Improvement
            Reporter: Ivan Bessonov


The case is similar to https://issues.apache.org/jira/browse/IGNITE-25043, but 
somewhat worse: we move configuration from one place to another. It's too hard 
to introduce a flexible engine feature that would account for all possible 
types of such changes, so additional coding will be required for every such an 
occasion.

Anyway, please familiarize yourself with 
https://issues.apache.org/jira/browse/IGNITE-25041, and its implementation if 
it's available. This implementation will be similar.
h3. Implementation notes

I suggest supporting {{@Deprecated}} annotation for configuration properties. 
We will be able to read deprecated values, but we won't show them to the user 
anymore, and these values will be deleted from the configuration storage. The 
difference between deprecated and deleted configuration is the following:
 * We're still able to read the value of deprecated configuration in code 
before it's lost forever.

This allows us to have a migration code for deprecated configurations, in which 
we would copy old values to the new place. I propose the following algorithm:

We have two distinct cases where we could receive a value of deprecated 
configuration, and handling them will be different in the implementation.
h4. 1. Configuration Storage

Here we should perform a transparent migration. When starting a node or 
finishing join to the cluster, we should read "old" value. If it is not 
default, we should run a migration routine, that would convert it to "new" 
value, and set "default" to "old" value, thus making it effectively unused.

When working with these properties in the code, two options are possible:
 * Configuration is local. We should only use "new" values, because 
configuration has been migrated before we started our component.
 * Configuration is global (cluster configuration). We should use "old" value 
if it has non-default value, because we have a small window of time when 
migration has not yet happened. If the value is default, we should use "new" 
configuration. Same goes for configuration update listeners - we should have 
them for both "old" and "new" configurations.

h4. 2. Dynamic configuration updates

Given that "old" values should no be present in configuration storages, we 
can't propagate them via regular configuration lifecycle - they'll be lost in 
such a case.

 _Configuration must be migrated before it is written to the storage._

I suggest registering our migration routines in configuration changer instance 
itself, so that every time user passes some configuration values to us, we:
 * Parse it.
 * Apply to current configuration tree.
 * Also apply a migration routine to the same configuration tree ({*}new 
step{*}).
 * Send this update to configuration storage (proceed with regular flow).

I suppose we can identify modified sub-trees and this only run the routines 
that match the specific subtrees, in order to not do these calculations 
constantly.

I know it all sounds abstract. In speudo-code, I would like to see the 
following:

 
{code:java}
MyConfigurationModule {
  migrationRoutines() {
    return Map.of(OldConfigurationSchema.class, superRoot -> {
      var barValue = superRoot.foo().oldConfiguration().bar()
      if (barValue != BAR_DEFAULT) {
        superRoot.changeFoo().changeOldConfiguration().changeBar(BAR_DEFAULT)
        superRoot.changeNewFoo().changeBar(barValue)
      }
    })
  }
}{code}
The closure will be executed in a corresponding context automatically. I hope 
that it clears my idea.

 

The migration code will always be written by a developer. If it needs to be 
documented - we should document it.
h4. Deletion

Eventually, old configuration should be deleted from the code, with the 
migration routine. This should only be done when we declare some versions as 
incompatible, for example we could one day say {_}"you can't migrate directly 
from 3.0 to 3.3 without an intermediate 3.2 upgrade"{_}, that would be fine I 
think.

 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to