Skip to content

Commit 50fd10b

Browse files
committed
Record setting updater
1 parent f59b16d commit 50fd10b

File tree

2 files changed

+68
-6
lines changed

2 files changed

+68
-6
lines changed

server/src/main/java/org/elasticsearch/common/settings/Setting.java

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,10 +1319,6 @@ private static class RecordSetting<R extends Record> extends Setting<R> {
13191319
Property... properties
13201320
) {
13211321
super(new GroupKey(keyWithDot(key)), (s) -> "", (s) -> null, properties);
1322-
if (isDynamic()) {
1323-
// TODO
1324-
throw new IllegalArgumentException("Dynamic record settings not supported");
1325-
}
13261322
this.key = key;
13271323
this.recordClass = recordClass;
13281324
this.validator = r -> {}; // TODO: validator
@@ -1391,7 +1387,30 @@ public void diff(Settings.Builder builder, Settings source, Settings defaultSett
13911387

13921388
@Override
13931389
public AbstractScopedSettings.SettingUpdater<R> newUpdater(Consumer<R> consumer, Logger logger, Consumer<R> validator) {
1394-
throw new IllegalStateException("setting [" + getKey() + "] is not dynamic");
1390+
return new AbstractScopedSettings.SettingUpdater<R>() {
1391+
@Override
1392+
public boolean hasChanged(Settings current, Settings previous) {
1393+
return false == get(current).equals(get(previous));
1394+
}
1395+
1396+
@Override
1397+
public R getValue(Settings current, Settings previous) {
1398+
// TODO: What am I supposed to do with previous? Javadocs don't say
1399+
R result = get(current);
1400+
validator.accept(result);
1401+
return result;
1402+
}
1403+
1404+
@Override
1405+
public void apply(R value, Settings current, Settings previous) {
1406+
consumer.accept(value);
1407+
}
1408+
1409+
@Override
1410+
public String toString() {
1411+
return "Updater for record: " + recordClass.getName();
1412+
}
1413+
};
13951414
}
13961415

13971416
@SuppressForbidden(reason = "To support arbitrary record types, we must invoke the constructor with invokeWithArguments")

server/src/test/java/org/elasticsearch/common/settings/SettingTests.java

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1610,7 +1610,50 @@ public void testLongSettingBounds() {
16101610
public void testRecordSetting() {
16111611
record TestSetting(int intSetting) {}
16121612
Setting<TestSetting> setting = Setting.recordSetting("record.setting", TestSetting.class, MethodHandles.lookup(), List.of());
1613-
assertEquals(new TestSetting(123), setting.get(Settings.builder().put("record.setting.int_setting", 123).build()));
1613+
Settings settings123 = Settings.builder().put("record.setting.int_setting", 123).build();
1614+
Settings settings456 = Settings.builder().put("record.setting.int_setting", 456).build();
1615+
1616+
assertEquals(new TestSetting(123), setting.get(settings123));
16141617
assertThrows(IllegalStateException.class, () -> setting.get(Settings.EMPTY));
1618+
1619+
var watcher = new AtomicReference<TestSetting>(null);
1620+
var updater = setting.newUpdater(watcher::set, logger);
1621+
assertNull("Creating an updater does not call set", watcher.get());
1622+
updater.apply(settings456, settings123);
1623+
assertEquals("Updater called when value changed", new TestSetting(456), watcher.get());
1624+
assertThrows("Throws when there's no default", IllegalStateException.class, ()->updater.apply(Settings.EMPTY, settings456));
1625+
1626+
watcher.set(null);
1627+
updater.apply(settings123, settings123);
1628+
assertNull("Updater NOT called when value unchanged", watcher.get());
1629+
updater.apply(settings456, settings456);
1630+
assertNull("Updater again not called when value unchanged", watcher.get());
1631+
}
1632+
1633+
public void testRecordWithDefaults() {
1634+
record TestSetting(int i1, int i2) {}
1635+
Setting<Integer> i1Setting = Setting.intSetting("record.setting.i1", -1);
1636+
Setting<Integer> i2Setting = Setting.intSetting("record.setting.i2", -2);
1637+
Setting<TestSetting> setting = Setting.recordSetting("record.setting", TestSetting.class, MethodHandles.lookup(), List.of(i1Setting, i2Setting));
1638+
Settings settings123 = Settings.builder().put("record.setting.i1", 123).build();
1639+
1640+
assertEquals(new TestSetting(123, 456), setting.get(Settings.builder().put("record.setting.i1", 123).put("record.setting.i2", 456).build()));
1641+
assertEquals(new TestSetting(-1, 456), setting.get(Settings.builder().put("record.setting.i2", 456).build()));
1642+
assertEquals(new TestSetting(-1, -2), setting.get(Settings.EMPTY));
1643+
1644+
var watcher = new AtomicReference<TestSetting>(null);
1645+
var updater = setting.newUpdater(watcher::set, logger);
1646+
updater.apply(settings123, Settings.EMPTY);
1647+
assertEquals(new TestSetting(123, -2), watcher.get());
1648+
updater.apply(Settings.EMPTY, settings123);
1649+
assertEquals(new TestSetting(-1, -2), watcher.get());
1650+
1651+
Settings explicitDefaults = Settings.builder().put("record.setting.i1", -1).put("record.setting.i2", -2).build();
1652+
watcher.set(null);
1653+
updater.apply(Settings.EMPTY, explicitDefaults);
1654+
assertNull("Updater NOT called when value deleted from the default", watcher.get());
1655+
updater.apply(explicitDefaults, Settings.EMPTY);
1656+
assertNull("Updater NOT called when value 'changed' to the default from nothing", watcher.get());
16151657
}
1658+
16161659
}

0 commit comments

Comments
 (0)