Skip to content

Refactor usage of compatible version #68648

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

Merged
merged 10 commits into from
Feb 10, 2021

Conversation

pgomulka
Copy link
Contributor

@pgomulka pgomulka commented Feb 8, 2021

Compatible API version is at the moment represented by both Version and
byte - representing a major version. This can lead to a confusion which
representation to use, as well as to incorrect assumptions that minor
versions are supported (with the use of Version.V_7_0_0)

Current usage of XContentParser.useCompatible is also not allowing to
define two compatible implementations. This is not about
support N-2 compatibility, but to allow to continue development when a
major release is performed.

This commit is introducing the CompatibleVersion object responsible for
wrapping around a major version of compatible API.

relates #68100

Compatible API version is at the moment represented by both Version and
byte - representing a major version. This can lead to a confusion which
representation to use, as well as to incorrect assumptions that minor
versions are supperted (with the use of Version.V_7_0_0)

Current usage of XContentParser.useCompatible is also not allowing to
define two compatibile implementations. This is not about
support N-2 compatibility, but to allow to continue development when a
major release is performed.

This commit is introducing the  CompatibleVersion object responsible for
wrapping around a major version of compatible API.
@pgomulka pgomulka added :Core/Infra/REST API REST infrastructure and utilities v8.0.0 labels Feb 8, 2021
@pgomulka pgomulka self-assigned this Feb 8, 2021
@elasticmachine elasticmachine added the Team:Core/Infra Meta label for core/infra team label Feb 8, 2021
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra (Team:Core/Infra)

Copy link
Contributor

@jakelandis jakelandis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the enumeration... as mentioned in the comment, I think it addresses all the concerns I had that motivated the use for a boolean

I think

if([builder|parser|request].getRestApiCompatibleVersion() == RestApiCompatibileVersion.V7) 
{ //

reads pretty nice and no need for the boolean.

Otherwise just a few nit picks.

return restCompatibilityVersion;
}

public boolean useCompatibility(CompatibleVersion codeChangeVersion) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... now seeing this with the new enum, not sure if like the boolean approach.

if(builder.getRestApiCompatibleVersion() == RestApiCompatibileVersion.V7) 
{ //do something special

I think reads pretty well, and looks alot (different enough) from the wire protocol ...its a bit verbose, but such is Java.

I think the enum introduced here resolved any issues I had that led me to suggest the boolean approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I personally prefer to replace boolean expressions with named methods, but in this case it would be an overdo.
I also realised that we can apply the same 'getter' style to parser


V_8(8),
V_7(7),
V_6(6);//used in testing, to prove validation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way to avoid declaring this even for testing ? Having 6 in here, even with the comment is a bit misleading since it will show up in the auto complete.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this should ideally be removed, but at the same time I won't be able to test the validation against incorrect registration RestController#registerHandlerNoWrap
This is a real scenario that we will have during the major release (3 versions present)

 private void registerHandlerNoWrap(RestRequest.Method method, String path, RestHandler maybeWrappedHandler) {
        final RestApiCompatibleVersion version = maybeWrappedHandler.compatibleWithVersion();
        assert RestApiCompatibleVersion.minimumSupported() == version || RestApiCompatibleVersion.currentVersion() == version
            : "REST API compatibility is only supported for version " + RestApiCompatibleVersion.minimumSupported().major;

Copy link
Contributor Author

@pgomulka pgomulka Feb 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my point is that I expect that declaration within Plugin.getRestHandlers of compatible handlers must be done under if statements. If we forget about this the assertion in registerHandlerNoWrap should fail

if(RestApiCompatibleVersion.minimumSupported == RestApiCompatibleVersion.V_8)
//register v8
if(RestApiCompatibleVersion.currentVersion == RestApiCompatibleVersion.V_7)
//register v7

Even thought those handlers would not be accessible when requested anyway (the validation in RestCompatibleVersionHandler would prevent a request with application/vnd.elasticsearch+json;compatible-with=6 )
I would prefer we don't even try to register them.

V_7(7),
V_6(6);//used in testing, to prove validation

// This needs to be aligned with Version.CURRENT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be codified with an assert ? It will trip when cutting the new branch, but here I think that is desirable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, but the assert will have to be in Version class (dependency direction)

return valueOf("V_" + majorVersion);
}

public static CompatibleVersion minimumRestCompatibilityVersion() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

RestApiCompatibleVersion getMinimumSupported() 

To avoid duplication in the naming.

@@ -155,7 +157,7 @@ public static XContentBuilder builder(XContentType xContentType, Set<String> inc
*/
private boolean humanReadable = false;

private byte compatibleMajorVersion;
private CompatibleVersion restCompatibilityVersion;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: restApiCompatibility

public XContentBuilder withCompatibleVersion(CompatibleVersion compatibleVersion) {
assert this.restCompatibilityVersion == null : "Compatible version has already been set";
if (compatibleVersion == null) {
throw new IllegalArgumentException("Compatible major version must not be null");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the message needs to be updated. Also, can probably use Objects.requireNonNull

V_6(6);//used in testing, to prove validation

// This needs to be aligned with Version.CURRENT
public static final CompatibleVersion CURRENT = V_8;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if we could hide the CURRENT, so a user can't type CompatibleVersion.CURRENT since in all but the core cases (like parsing the header) it would be incorrect to do so.

It's a pretty minor concern ... maybe a simple comment would suffice ? , or maybe a getCurrentVersion() (with java doc saying dont use this) instead to avoid it looking like one of the enum options?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, I feel getCurrentVersion can help here.

@pgomulka
Copy link
Contributor Author

pgomulka commented Feb 9, 2021

@elasticmachine update branch

Copy link
Contributor

@jakelandis jakelandis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 last comments (remove v_6 (and associated test), and boolean method)... assuming that LGTM. I like really like this approach, thanks for the iterations.


V_8(8),
V_7(7),
V_6(6);//used in testing, to prove validation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed in person, we can remove this (V_6) and the associated test, we can have other ways to ensure elder version are not in use, and this would probably cause more confusion (even with the comment) then would help.

Copy link
Contributor Author

@pgomulka pgomulka Feb 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, removed the instance and the test

return restApiCompatibilityVersion;
}

public boolean useCompatibility(RestApiCompatibleVersion codeChangeVersion) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be removed ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, missed it. thanks

@pgomulka pgomulka merged commit 71d43b5 into elastic:master Feb 10, 2021
Copy link
Member

@jaymode jaymode left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and looked even though its been merged. Looks great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Core/Infra/REST API REST infrastructure and utilities >refactoring Team:Core/Infra Meta label for core/infra team v8.0.0-alpha1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants