Skip to content
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

Conversation

andyb-elastic
Copy link
Contributor

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.

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.
@andyb-elastic andyb-elastic added >feature :Search Relevance/Suggesters "Did you mean" and suggestions as you type v7.0.0 v6.4.0 labels May 1, 2018
@andyb-elastic andyb-elastic requested a review from jimczi May 1, 2018 01:13
@hub-cap hub-cap added :Search Relevance/Suggesters "Did you mean" and suggestions as you type and removed :Search Relevance/Suggesters "Did you mean" and suggestions as you type labels May 1, 2018
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-search-aggs

Copy link
Contributor

@jimczi jimczi left a 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) {
Copy link
Contributor

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 ?

Copy link
Contributor Author

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

Copy link
Contributor

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
Copy link
Contributor

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.

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 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

Copy link
Contributor

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.

@andyb-elastic
Copy link
Contributor Author

Commits I just pushed do the following

  • Suggester spec only registers one reader for its Suggestion response
  • Move custom suggester to example plugin
  • Add yaml rest test for example plugin that mirrors the existing CustomSuggesterSearchIT

Things I need to do next

  • Change Suggest's xcontent handling so that custom fields in Suggestion and Entry can be written (I'm not 100% sure we want to do this but it seems pretty reasonable for users to expect that they can extend this)
  • Remove the old custom suggester tests in server-test

@andyb-elastic
Copy link
Contributor Author

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?

Copy link
Contributor

@jimczi jimczi left a 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)) {
Copy link
Contributor

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");
Copy link
Contributor

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)) {
Copy link
Contributor

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
@andyb-elastic
Copy link
Contributor Author

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
@andyb-elastic
Copy link
Contributor Author

Jenkins run gradle build tests please

@andyb-elastic
Copy link
Contributor Author

Jenkins run gradle build tests please

1 similar comment
@andyb-elastic
Copy link
Contributor Author

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
@andyb-elastic
Copy link
Contributor Author

@jimczi I pushed the serialization tests we talked about

@andyb-elastic
Copy link
Contributor Author

Jenkins run gradle build tests please

Copy link
Contributor

@jimczi jimczi left a 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);
Copy link
Contributor

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 ?

Copy link
Contributor Author

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

@andyb-elastic
Copy link
Contributor Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>feature :Search Relevance/Suggesters "Did you mean" and suggestions as you type v7.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants