Modify process for deserializing DynamicCoordinatorConfig#12615
Modify process for deserializing DynamicCoordinatorConfig#12615capistrant wants to merge 10 commits intoapache:masterfrom
Conversation
|
This is an interesting fix, @capistrant ! Some observations: There is a similar discrepancy between the POST and GET of the config. While the POST API payload is read as a Builder, the response of the GET API is still the actual config object. This probably makes sense as the user should be allowed to omit nullable fields in the POST payload but while reading the config, they should get back the fully validated and null-handled config. But I think we should call this out clearly in the javadocs that we must always:
B) Another fishy thing is the The fix here would be to simply get rid of this method and this weird logic. Both API and console users would be affected as their old assumptions (if any) about carrying forward omitted values would break. Although, this would not be a hindrance to the end goal of this PR and need not be handled here. @gianm , @capistrant , what do you think? |
| * @param configManager {@link JacksonConfigManager } responsible for managing persisted druid configuration content | ||
| * @return {@link AtomicReference} of {@link CoordinatorDynamicConfig.Builder} | ||
| */ | ||
| public static AtomicReference<CoordinatorDynamicConfig.Builder> watch(final JacksonConfigManager configManager) |
There was a problem hiding this comment.
I think we should also make this method private while we are at it as it is not being used anywhere except this class itself. We also already have the current method which is much more convenient. I can't think of a use case where watch() would be needed.
There was a problem hiding this comment.
The above javadoc could then be updated and moved to the current() method.
|
@capistrant , any thoughts on this? |
|
This pull request has been marked as stale due to 60 days of inactivity. |
|
This pull request/issue has been closed due to lack of activity. If you think that |
Fixes #11161.
Description
Modified the deserialization of DynamicCoordinatorConfig
The coordinator now uses the
DynamicCoordinatorConfig.Builder.classfor deserialization of the dynamic coordinator config. This allows us to automatically use the Builder specified default for a configuration key that does not exist in the metastore payload for the dynamic config. Doing so ensures that an "incomplete" config in the metastore will be supplemented with the proper Druid specified defaults every time it is deserialized.Prior to this change, Druid used
DynamicCoordinatorConfig.classdirectly for deserialization. The drawback on this is thatDynamicCoordinatorConfigis less equipped for cleanly handling missing configuration keys during deserialization. If a developer used a Java primitive when adding a new config, on upgrade, the deserialization would use the Java system default for a missing value. This is often times very bad! For instance, I might addnewIntConfigto Druid. Since this isn't in the previous version of Druid, upgrading the coordinator would cause deserialization of the legacy config to populate newIntConfig with the value0. But as a developer, I needednewIntConfigto default to 100. To work-a-round this, I would flip the type toIntegerwhich would deserialize a missing value asnull. I could then check for this null value in the constructor and replace it with the desired default from the Builder class constants. You can see a more realistic example of this work-a-round here Another reference to this conditional null check comes up in this thread.My change gets us away from this pattern. We are catching an undesirable state and deferring to the default in the Builder class already... so why not just use the Builder for deserialization is my thought. This way we can leverage the built in patterns for handling nulls and replacing them with constant defaults there instead of the
DynamicCoordinatorConfigMy one worry is that I am missing an angle here that required us to forgo the Builder for this deserialization. At first instance, I figured that serialization used the same
ConfigManagerwatcher and that using the builder for serde would cause issues in writing the config. However, this does not seem to be the case after running automated tests, manual review of the config update code path, and testing this change in my local druid cluster. Still, perhaps I am overlooking something that has prevented us from using the builder. That is what I'm hoping the review process can smoke out.What I did not touch in this PR
I did not alter any of the code in the
CoordinatorDynamicConfigconstructor that is performing the deserialization work-a-round that my update is intended to prevent. I could certainly make that change here as well, but I wanted to be conservative with the scope of this change and guarantee no change in behavior of existing code. Removing the conditional checks on null and changing the variables to primitive types would change behavior IF there were any use of theCoordinatorDynamicConfigconstructor directly. To my knowledge, unit tests are the only place this still happens.Key changed/added classes in this PR
CoordinatorDynamicConfigThis PR has: