diff --git a/server/src/main/java/org/apache/druid/server/coordinator/CoordinatorDynamicConfig.java b/server/src/main/java/org/apache/druid/server/coordinator/CoordinatorDynamicConfig.java index 90574780eabe..6e073e678e35 100644 --- a/server/src/main/java/org/apache/druid/server/coordinator/CoordinatorDynamicConfig.java +++ b/server/src/main/java/org/apache/druid/server/coordinator/CoordinatorDynamicConfig.java @@ -216,19 +216,29 @@ private static Set parseJsonStringOrArray(Object jsonStringOrArray) } } - public static AtomicReference watch(final JacksonConfigManager configManager) + /** + * Setup a watch on the {@link CoordinatorDynamicConfig} in order to ensure access to the latest stored version of the config. + * + * Note that the {@link CoordinatorDynamicConfig.Builder} class is used here for serde because that allows clean setting of + * defaults for missing configuation keys. Missing configuration keys are common in cases such as the addition of a + * new config key in a new Druid version. + * + * @param configManager {@link JacksonConfigManager } responsible for managing persisted druid configuration content + * @return {@link AtomicReference} of {@link CoordinatorDynamicConfig.Builder} + */ + public static AtomicReference watch(final JacksonConfigManager configManager) { return configManager.watch( CoordinatorDynamicConfig.CONFIG_KEY, - CoordinatorDynamicConfig.class, - CoordinatorDynamicConfig.builder().build() + CoordinatorDynamicConfig.Builder.class, + CoordinatorDynamicConfig.builder() ); } @Nonnull public static CoordinatorDynamicConfig current(final JacksonConfigManager configManager) { - return Preconditions.checkNotNull(watch(configManager).get(), "Got null config from watcher?!"); + return Preconditions.checkNotNull(watch(configManager).get().build(), "Got null config from watcher?!"); } @JsonProperty("millisToWaitBeforeDeleting") diff --git a/server/src/test/java/org/apache/druid/server/coordinator/DruidCoordinatorTest.java b/server/src/test/java/org/apache/druid/server/coordinator/DruidCoordinatorTest.java index 7b2840d0e213..fa7e72289d17 100644 --- a/server/src/test/java/org/apache/druid/server/coordinator/DruidCoordinatorTest.java +++ b/server/src/test/java/org/apache/druid/server/coordinator/DruidCoordinatorTest.java @@ -131,7 +131,7 @@ public void setUp() throws Exception EasyMock.anyObject(Class.class), EasyMock.anyObject() ) - ).andReturn(new AtomicReference(CoordinatorDynamicConfig.builder().build())).anyTimes(); + ).andReturn(new AtomicReference(CoordinatorDynamicConfig.builder())).anyTimes(); EasyMock.expect( configManager.watch( EasyMock.eq(CoordinatorCompactionConfig.CONFIG_KEY), @@ -715,6 +715,9 @@ public void testBalancerThreadNumber() EasyMock.expect(dynamicConfig.getBalancerComputeThreads()).andReturn(5).times(2); EasyMock.expect(dynamicConfig.getBalancerComputeThreads()).andReturn(10).once(); + CoordinatorDynamicConfig.Builder dynamicConfigBuilder = EasyMock.createNiceMock(CoordinatorDynamicConfig.Builder.class); + EasyMock.expect(dynamicConfigBuilder.build()).andReturn(dynamicConfig).anyTimes(); + JacksonConfigManager configManager = EasyMock.createNiceMock(JacksonConfigManager.class); EasyMock.expect( configManager.watch( @@ -722,10 +725,10 @@ public void testBalancerThreadNumber() EasyMock.anyObject(Class.class), EasyMock.anyObject() ) - ).andReturn(new AtomicReference(dynamicConfig)).anyTimes(); + ).andReturn(new AtomicReference(dynamicConfigBuilder)).anyTimes(); ScheduledExecutorFactory scheduledExecutorFactory = EasyMock.createNiceMock(ScheduledExecutorFactory.class); - EasyMock.replay(configManager, dynamicConfig, scheduledExecutorFactory); + EasyMock.replay(configManager, dynamicConfig, scheduledExecutorFactory, dynamicConfigBuilder); DruidCoordinator c = new DruidCoordinator( druidCoordinatorConfig, @@ -998,7 +1001,7 @@ public void testCoordinatorCustomDutyGroupsRunAsExpected() throws Exception EasyMock.anyObject(Class.class), EasyMock.anyObject() ) - ).andReturn(new AtomicReference(CoordinatorDynamicConfig.builder().build())).anyTimes(); + ).andReturn(new AtomicReference(CoordinatorDynamicConfig.builder())).anyTimes(); EasyMock.expect( configManager.watch( EasyMock.eq(CoordinatorCompactionConfig.CONFIG_KEY),