-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[improve][broker] PIP-300: Add custom dynamic configuration for plugins #20884
Changes from all commits
2da728d
ce1ed61
ddd0552
6da5743
768143a
34c8e84
459a9f1
6c653a9
a2e2bad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2514,22 +2514,25 @@ private void handleDynamicConfigurationUpdates() { | |
return; | ||
} | ||
Field configField = configFieldWrapper.field; | ||
Object newValue = FieldParser.value(data.get(configKey), configField); | ||
if (configField != null) { | ||
Consumer listener = configRegisteredListeners.get(configKey); | ||
try { | ||
Object existingValue = configField.get(pulsar.getConfiguration()); | ||
Consumer listener = configRegisteredListeners.get(configKey); | ||
try { | ||
final Object existingValue; | ||
final Object newValue; | ||
if (configField != null) { | ||
newValue = FieldParser.value(data.get(configKey), configField); | ||
existingValue = configField.get(pulsar.getConfiguration()); | ||
configField.set(pulsar.getConfiguration(), newValue); | ||
log.info("Successfully updated configuration {}/{}", configKey, | ||
data.get(configKey)); | ||
if (listener != null && !existingValue.equals(newValue)) { | ||
listener.accept(newValue); | ||
} | ||
} catch (Exception e) { | ||
log.error("Failed to update config {}/{}", configKey, newValue); | ||
} else { | ||
newValue = value; | ||
existingValue = configFieldWrapper.customValue; | ||
configFieldWrapper.customValue = newValue == null ? null : String.valueOf(newValue); | ||
} | ||
} else { | ||
log.error("Found non-dynamic field in dynamicConfigMap {}/{}", configKey, newValue); | ||
log.info("Successfully updated configuration {}/{}", configKey, data.get(configKey)); | ||
if (listener != null && !Objects.equals(existingValue, newValue)) { | ||
listener.accept(newValue); | ||
} | ||
} catch (Exception e) { | ||
log.error("Failed to update config {}", configKey, e); | ||
} | ||
}); | ||
}); | ||
|
@@ -2968,20 +2971,27 @@ public <T> void registerConfigurationListener(String configKey, Consumer<T> list | |
|
||
private void addDynamicConfigValidator(String key, Predicate<String> validator) { | ||
validateConfigKey(key); | ||
if (dynamicConfigurationMap.containsKey(key)) { | ||
dynamicConfigurationMap.get(key).validator = validator; | ||
} | ||
dynamicConfigurationMap.get(key).validator = validator; | ||
} | ||
|
||
private void validateConfigKey(String key) { | ||
try { | ||
ServiceConfiguration.class.getDeclaredField(key); | ||
} catch (Exception e) { | ||
log.error("ServiceConfiguration key {} not found {}", key, e.getMessage()); | ||
throw new IllegalArgumentException("Invalid service config " + key, e); | ||
if (!dynamicConfigurationMap.containsKey(key)) { | ||
throw new IllegalArgumentException(key + " doesn't exits in the dynamicConfigurationMap"); | ||
} | ||
} | ||
|
||
/** | ||
* Allows the third-party plugin to register a custom dynamic configuration. | ||
*/ | ||
public void registerCustomDynamicConfiguration(String key, Predicate<String> validator) { | ||
if (dynamicConfigurationMap.containsKey(key)) { | ||
throw new IllegalArgumentException(key + " already exists in the dynamicConfigurationMap"); | ||
} | ||
ConfigField configField = ConfigField.newCustomConfigField(null); | ||
configField.validator = validator; | ||
dynamicConfigurationMap.put(key, configField); | ||
} | ||
|
||
private void createDynamicConfigPathIfNotExist() { | ||
try { | ||
Optional<Map<String, String>> configCache = | ||
|
@@ -3356,13 +3366,24 @@ public void unblockDispatchersOnUnAckMessages(List<PersistentDispatcherMultipleC | |
} | ||
|
||
private static class ConfigField { | ||
// field holds the pulsar dynamic configuration. | ||
final Field field; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why you can't reuse this field? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For external dynamic configuration, when using the The purpose of this value is to compare with the old configuration value and notify the user. |
||
|
||
// customValue holds the external dynamic configuration. | ||
volatile String customValue; | ||
|
||
Predicate<String> validator; | ||
|
||
public ConfigField(Field field) { | ||
super(); | ||
this.field = field; | ||
} | ||
|
||
public static ConfigField newCustomConfigField(String customValue) { | ||
ConfigField configField = new ConfigField(null); | ||
configField.customValue = customValue; | ||
return configField; | ||
} | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if
customValue
equals null?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
customValue
defaults to null, when the config has been changed, this value will be updated, seeconfigFieldWrapper.customValue = String.valueOf(newValue);
.