-
Notifications
You must be signed in to change notification settings - Fork 57
Support yaml partially #262
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
base: master
Are you sure you want to change the base?
Conversation
Hi, thank you for the patch and sorry for the late review. Could you resolve the conflict, for the ease of review? |
0c972cf
to
37bb1f3
Compare
...test/java/com/linecorp/decaton/centraldogma/CentralDogmaPropertySupplierIntegrationTest.java
Show resolved
Hide resolved
rebased! |
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.
Left one early question, but overall strategy looks good.
Please go ahead and complete the implementation. Thanks for the patch!
} | ||
|
||
rootWatcher.watch(node -> { | ||
node.fields().forEachRemaining(entry -> { |
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.
In contrast to current approach, new code sets the watch against entire file and iterates through all properties in the file.
Do you have any thoughts if it will cause some downside comparing to current approach?
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.
I think there's almost no difference in practice!
The current decaton implementation uses Central Dogma’s MappingWatcher
for each key/property, which attaches a child watcher to a root watcher.
When the root watcher's content (=JSON) changes, each child watcher is triggered independently.
All it does is extract the value for a specific key from the root JSON content and notify its listener only if the value has changed.
In this PR, it delegats that logic to DynamicProperty#checkingSet
, which also compares the previous and new values and does not notify listeners unless there’s an actual change.
decaton/processor/src/main/java/com/linecorp/decaton/processor/runtime/DynamicProperty.java
Lines 71 to 116 in b795c1e
public T set(T value) { setLock.lock(); try { T currentValue = this.value; if (currentValue == null && value == null || currentValue != null && currentValue.equals(value)) { // No need to update. return null; } validate(value); this.value = value; logger.debug("Property {} has been updated ({} => {})", name(), currentValue, value); notifyListeners(currentValue, value); return currentValue; } finally { setLock.unlock(); } } /** * Update the value of this property, taking untyped object as an argument. * * This is a slightly different version of {@link #set}. * Before calling {@link #set}, this method check if the passed value's runtime class is matching to the * type configured as {@link PropertyDefinition#runtimeType()}. * @param value new value to set to this property. * @return old value which was set to this property. null if there was no update because the new value was * equivalent to the current value. * * @throws IllegalArgumentException when invalid value passed. */ public T checkingSet(Object value) { Class<?> runtimeType = definition().runtimeType(); if (value != null && runtimeType != null && !runtimeType.isInstance(value)) { throw new IllegalArgumentException(String.format( "type %s is not applicable for property %s of type %s", value.getClass().getCanonicalName(), name(), runtimeType.getCanonicalName())); } return set(safeCast(value)); }
As for the listeners, the number of change notifications won’t differ. The only difference is which layer is responsible for delivering them (Central Dogma vs Decaton).
There might be some difference in terms of parallelism for notifying new value.
Decaton has about 15 properties, and with the current implementation, Central Dogma watchers can run in parallel (as long as the Central Dogma executor allows it).
This PR updates are currently handled sequentially, but considering that the keys and values are very small, the impact is likely negligible.
decaton/processor/src/main/java/com/linecorp/decaton/processor/runtime/ProcessorProperties.java
Lines 259 to 272 in d5dae11
CONFIG_IGNORE_KEYS, CONFIG_PROCESSING_RATE, CONFIG_PARTITION_CONCURRENCY, CONFIG_MAX_PENDING_RECORDS, CONFIG_COMMIT_INTERVAL_MS, CONFIG_GROUP_REBALANCE_TIMEOUT_MS, CONFIG_SHUTDOWN_TIMEOUT_MS, CONFIG_LOGGING_MDC_ENABLED, CONFIG_BIND_CLIENT_METRICS, CONFIG_DEFERRED_COMPLETE_TIMEOUT_MS, CONFIG_PROCESSOR_THREADS_TERMINATION_TIMEOUT_MS, CONFIG_PER_KEY_QUOTA_PROCESSING_RATE, CONFIG_RETRY_TASK_IN_LEGACY_FORMAT, CONFIG_LEGACY_PARSE_FALLBACK_ENABLED));
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.
oops, we might want to avoid using node.fields()
in this change, and instead explicitly check properties based on ProcessorProperties#PROPERTY_DEFINITIONS
.
There’s no benefit in processing keys that Decaton doesn’t care about. Let me modify this point, though it's not main part for your question...
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.
Thank you for the detailed explanation including the implementation of CD!
I see, then the strategy looks good.
1f19274
to
3db6826
Compare
3db6826
to
3ec1618
Compare
Thank you. I've fixed failed tests while keeping the overall strategy. Please review when you have time 🙏 |
centraldogma/src/main/java/com/linecorp/decaton/centraldogma/CentralDogmaPropertySupplier.java
Outdated
Show resolved
Hide resolved
98fb0a9
to
0c1da8a
Compare
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.
Sorry for the late review.
Left only one minor comment. overall LGTM!
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.
This class doesn't need to be exposed to users, so let's move to internal
package (refs: https://github.com/line/decaton/blob/master/VERSIONING.md#public-apis)
JsonFormat, YamlFormat as well
As far as I know, inline comments are often necessary for
CONFIG_IGNORE_KEYS
,CONFIG_PARTITION_CONCURRENCY
, andCONFIG_MAX_PENDING_RECORDS
.Using YAML allows us to add inline comment in central dogma decaton property file.
Decaton's internal parser is Jackson, which seems to partially support YAML. By leveraging this, YAML can be supported with relatively few changes.
Of course, it’s not complete. While YAML tags, anchors, and aliases cannot be used, we can include comments in the configuration file. Practically speaking, this seems to be sufficient...
If maintainers don't want to use YAML with parital support, there are some Jackson options that support JSON5 to support comment in json file.
If it's acceptable for decaton maintainers that partial yaml support, major version up is necessary as a breaking change to accommodate users (though I don't think they exist) who might have a YAML file extension but use JSON.
Resolve #173