-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
serialize suggestion responses as named writeables #30284
serialize suggestion responses as named writeables #30284
Conversation
Suggestion responses were previously serialized as streamables which made writing suggesters in plugins with custom suggestion response types impossible. This commit makes them serialized as named writeables and provides a facility for registering a reader for suggestion responses when registering a suggester. This also makes Suggestion responses abstract, requiring a suggester implementation to provide its own types. Suggesters which do not need anything additional to what is defined in Suggest.Suggestion should provide a minimal subclass.
Pinging @elastic/es-search-aggs |
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.
Thanks @andyb-elastic , I left some comments.
addSuggestionReader(name, suggestionReader); | ||
} | ||
|
||
public SuggesterSpec addSuggestionReader(String writeableName, Writeable.Reader<? extends Suggest.Suggestion> reader) { |
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.
Is it needed to allow multiple readers ? Only one custom suggestion implementation should be needed here ?
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.
My thinking here was that it wouldn't be unreasonable for a suggester to return multiple types of suggestions in different situations. For example it looks like some aggregations do this if I'm not mistaken. But it makes sense and is simpler if they only use one, so I'll do that
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.
+1
@@ -135,7 +149,7 @@ protected XContentBuilder innerToXContent(XContentBuilder builder, Params params | |||
|
|||
@Override | |||
public String getWriteableName() { | |||
return "custom"; | |||
return SUGGESTION_NAME; | |||
} | |||
|
|||
@Override |
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.
Is it possible to move this test and the custom suggestion impl in the plugin examples and adds rest tests that checks that xcontent parsing works ? I am not sure that this IT test is enough to validate the plugin integration.
This would be nice to have a real example that shows how to write a custom suggester and the example plugins are the perfect fit for this.
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 agree on both, that this doesn't completely validate the plugin integration, and that it would be preferable to have it in an example plugin. I was going to make that a follow up PR but I'll add it to this one
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.
Thanks, +1 to add the example plugin in this pr.
Currently works with the Option dummy field, but Entry and Suggestion dummy fields don't make it into xcontent responses right now
Commits I just pushed do the following
Things I need to do next
|
to XContentFragments
I added a test for the ability to add custom fields for Entry subclasses. Also changed Suggestion/Entry/Option so that they're all xcontent fragments and their subclasses can add fields by overriding #toXContent @jimczi mind taking another look? |
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.
It looks great @andyb-elastic ! I left some comments regarding serializations and BWC but otherwise I think it's ready. Can you change the target version to 6.5 and add an entry in the breaking changes ?
@@ -92,6 +90,42 @@ public Suggest(List<Suggestion<? extends Entry<? extends Option>>> suggestions) | |||
this.hasScoreDocs = filter(CompletionSuggestion.class).stream().anyMatch(CompletionSuggestion::hasScoreDocs); | |||
} | |||
|
|||
public Suggest(StreamInput in) throws IOException { | |||
// in older versions, Suggestion types were serialized as Streamable | |||
if (in.getVersion().before(Version.V_6_4_0)) { |
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.
you need to start with 7.0 and change it when this is backported to 6.5 ?
suggestion = new CompletionSuggestion(in); | ||
break; | ||
case 2: // CompletionSuggestion.TYPE | ||
throw new IllegalArgumentException("Completion suggester 2.x is not supported anymore"); |
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 we can remove this, we don't support 2.x here (nor in 6.x).
out.writeVInt(command.getWriteableType()); | ||
command.writeTo(out); | ||
// in older versions, Suggestion types were serialized as Streamable | ||
if (out.getVersion().before(Version.V_6_4_0)) { |
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.
Same here, version should be 7 for now
Raise compatibility version to 7.0, remove serialization for the 2.x version of completion suggestions
It looks like there's a bug with serialization across mixed version clusters in the current state of this PR, I'm working on it |
Nodes using the old serialization have an innerReadFrom/WriteTo scheme for Suggestion objects and therefore write/read all of their one-off members before writing/reading their suggestion entries. This idiom makes it a little harder to follow and doesn't look like it survived the transition from Streamable to Writeable. This change makes it so that suggestions are still serialized in this old older when talking to older nodes, while using inheritance of just the single <init>(StreamInput) and writeTo(StreamOutput) methods for newer nodes
do this serialization as an obvious hack instead of leaving behind deprecated innerReadFrom/WriteTo methods which could have an ambiguous intent
Jenkins run gradle build tests please |
Jenkins run gradle build tests please |
1 similar comment
Jenkins run gradle build tests please |
More complicated equals behavior for options makes things start acting weird because the entry reduce code relies on them being equal if they have the same text. Arguably better to fix the entry reduce code but I'm not sure where else may rely on this behavior
@jimczi I pushed the serialization tests we talked about |
Jenkins run gradle build tests please |
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 left a minor comment regarding the serialization tests but LGTM otherwise. The change is relatively big so let's merge but we still need a follow up with a real BWC rest test.
|
||
public void testSerialization() throws IOException { | ||
final Version bwcVersion = VersionUtils.randomVersionBetween(random(), | ||
Version.CURRENT.minimumCompatibilityVersion(), Version.CURRENT); |
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.
We can test the versions before the change explicitly ?
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.
My thinking was that writing it like this, it will still make sense regardless of what the current version is. For example, there are plenty of tests like this hanging around that explicitly test versions that are now outside of the compatibility range, and I was thinking this is a way of avoiding that
Jim and I decided that we don't want to backport this to 6.x because the migration path for plugin authors is a little more involved than I'd originally thought - specifically that authors for who plugin suggesters are currently actually usable are likely using the plain Suggest.Suggestion response type, which this PR makes abstract |
This is still in-progress but I wanted to get it up for some feedback. I think the exact location of where some things (e.g. response fields) should go in the class hierarchy still needs to be cleaned up, as well as xcontent generation/parsing. The test coverage also probably could use some work.
The first stage of this will make suggestion responses named writeables and adapt CustomSuggesterIT accordingly, and then the second stage will move that test to an example plugin and make it a rest integration test.
This is related to #26585
Suggestion responses were previously serialized as streamables which
made writing suggesters in plugins with custom suggestion response types
impossible. This commit makes them serialized as named writeables and
provides a facility for registering a reader for suggestion responses
when registering a suggester.
This also makes Suggestion responses abstract, requiring a suggester
implementation to provide its own types. Suggesters which do not need
anything additional to what is defined in Suggest.Suggestion should
provide a minimal subclass.