-
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
Compatible logic for Removes typed endpoint from search and related APIs #54572
Conversation
fixed get/index tests CompatRestIT. test {yaml=get/21_stored_fields_with_types/Stored fields} CompatRestIT. test {yaml=get/71_source_filtering_with_types/Source filtering} CompatRestIT. test {yaml=index/70_mix_typeless_typeful/Index call that introduces new field mappings} CompatRestIT. test {yaml=index/70_mix_typeless_typeful/Index with typeless API on an index that has types} however the last one from get is still failing CompatRestIT. test {yaml=get/100_mix_typeless_typeful/GET with typeless API on an index that has
Pinging @elastic/es-core-infra (:Core/Infra/REST API) |
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 is really starting to take shape! I have a few comments and stopped with the repetitive comments (you can assume the same comment applies through out)
return List.of(new Route(GET, "/_mtermvectors"), | ||
new Route(POST, "/_mtermvectors"), | ||
new Route(GET, "/{index}/_mtermvectors"), | ||
new Route(POST, "/{index}/_mtermvectors"), |
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.
should the the above non-typed endpoints be here ? Shouldn't the this error trying to register the route ?
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 allow registering same method and path but under different version. (if someone tried to register same method and path and version twice - it would end with error)
We need this because multi term vectors (and most multi-* api) can have a type in a body. So a typed
request can be send via non-typed
endpoint.
|
||
/** | ||
* Parses a {@link RestRequest} body and returns a {@link MultiSearchTemplateRequest} | ||
* @param typeConsumer - is a function used when parsing a request body. if it contains a types field it will consume it, |
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.
can this be re-named keyAllowed
? (or the like)
A function used to validate if a provided xContent key is allowed. This is useful for xContent compatibility to determine if a key is allowed to be present in version agnostic manner. The provided function should return false if the key is not allowed.
(it is does not use the Consumer interface, and I believe it more general purpose then the just for types)
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.
good idea, I wasn't sure typeConsumer
was right as it was just too specific for type removal eample.
Will rename and update javadoc
import java.util.Set; | ||
import java.util.function.Function; | ||
|
||
public class TypeConsumer implements Function<String, Boolean> { |
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 this class has a couple problems...
it is named Consumer, but actually a Function with a side effect
it requires an ordering between methods. (e.g. if you call hasTypes can yield different results then calling apply then hasTypes)
hasTypes()
method feels utility like, and apply
is a pure function (which shouldn't have side effects even local to it's own class).
Can we separate this into two classes , a utility class and pure function class. If you need to hold to the state returned by the function, whoever calls that function can take that responsibility.
Also, in tangent with my other comment on renaming the variable, I think the function class be be generalized as well KeyAllowed
?
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.
Agree - the name is not right. The consumer was an initial idea but it ended up a function and I didn't change it accordingly. The KeyAllowed also feels right to me.
I am not sure I understand how to refactor this. My idea was that the typeConsumer
object being created at the V7 layer and passed down to v8 code can bubble up the state (information if type was found) back to v7 layer. Allowing the code to take action (most of the time just deprecation warning) to be present in v7 layer.
The apply()
method was meant to serve two functions. Retrieve and store the information for v7 layer if the type was found. And to tell v8 code that the key was allowed and exception when parsing is not necessary.
I also agree that side effect is probably unexpected. The TypeConsumer
is visible as just a Function
in v8 layer, so noone looking just at code which uses it would expect side effects.
If we have two classes, that would mean we would need to pass down two objects down to v8 layer?
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.
@jakelandis I think this is the main issue on that PR.
We can split this in two functions
- KeyAllowed<String,Boolean> - a function returning true if a string is of allowed value (_type, types etc) false otherwise. This will then be pass down into a Request parsing logic - i.e. https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/action/termvectors/TermVectorsRequest.java#L588
- second class - not sure about this one.. we need to go down from v7 rest layer to the same place where a request is parsed (v8 code).
I understand that it is not obvious that a function would has a state. But from the parsing point of view it wouldn't matter. All it care in TermVectorsRequest.java#L588 is if the field is allowed. The state if the field occurred (type for that example) is only relevant in v7 code where a class can be used directly (not by the Function interface)
If we were to have a utility class it would have live within some common to all modules utility module. That would not be ideal I guess.
We could refactor hasTypes to be a utility that is consuming the function that was passed down. But I am not sure this would benefit much (except from solving the ordering)
Anyways I think I might be missing something in your idea of splitting this class into two. Can you please give more details?
|
||
@Override | ||
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { | ||
request.param("type"); |
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.
Do you plan another round of PRs to issue deprecation and compatibility warnings ?
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 it would be good to include this in this PR too, so we could consider these API complete. Will revisit.
new Route(GET, "/{index}/_termvectors"), | ||
new Route(POST, "/{index}/_termvectors"), | ||
new Route(GET, "/{index}/_termvectors/{id}"), | ||
new Route(POST, "/{index}/_termvectors/{id}"), |
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.
are the non-typed endpoints needed ?
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 one also can expect a type in a body for all these paths (even non-typed) - hence it is using TypeConsumer
(to be renamed).
} | ||
readURIParameters(termVectorsRequest, request); | ||
|
||
if (typeConsumer.hasTypes()) { |
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.
If you move hasTypes a static method in a utility class, maybe we can push this logic (consume the type and log) there ?
new Route(GET, "/_msearch"), | ||
new Route(POST, "/_msearch"), | ||
new Route(GET, "/{index}/_msearch"), | ||
new Route(POST, "/{index}/_msearch"), |
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.
are the non-typed end points needed ?
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.
as per previous comments - type is present in a body
new Route(GET, "/_search"), | ||
new Route(POST, "/_search"), | ||
new Route(GET, "/{index}/_search"), | ||
new Route(POST, "/{index}/_search"), |
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.
non-typed endpoints ?
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.
type can be present as a parameter in v7 (as well as in a path for typed endpoints)
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.
although I am now not sure about INCLUDE_TYPE_NAME_PARAMETER
will revisit
new Route(GET, "/_msearch/template"), | ||
new Route(POST, "/_msearch/template"), | ||
new Route(GET, "/{index}/_msearch/template"), | ||
new Route(POST, "/{index}/_msearch/template"), |
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.
non-typed endpoints ?
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.
again - type can be present in a body.
This adds a compatible APIs for typed endpoints removed in #41640
202 failing tests
These 2 tests are explicitly fixed by this PR
CompatRestIT. test {yaml=mtermvectors/21_deprecated_with_types/Deprecated camel case and _ parameters should fail in Term Vectors query}
CompatRestIT. test {yaml=mtermvectors/30_mix_typeless_typeful/mtermvectors without types on an index that has types}
I think more yml tests should be added to 7.x to cover these endpoints
17th june
1306tests | 197failures | 16ignored | 10m56.91sduration