Refactor QueryRunner to accept QueryPlus: Query + QueryMetrics (part of #3798)#4184
Conversation
…t implementation, to replace QueryRunner.run(Query, Map).
| public Sequence<T> run(QuerySegmentWalker walker, Map<String, Object> context) | ||
| { | ||
| if (query instanceof BaseQuery) { | ||
| return ((BaseQuery) query).getQuerySegmentSpec().lookup(query, walker).run(this, context); |
There was a problem hiding this comment.
Why is this here instead of letting BaseQuery do it?
There was a problem hiding this comment.
It means that Query and BaseQuery should learn about QueryPlus, that I didn't want to happen.
There was a problem hiding this comment.
Oh, I see. Because "run" needs to get a QueryPlus, not a Query.
| String getType(); | ||
|
|
||
| /** | ||
| * @deprecated use {@link QueryPlus#run(QuerySegmentWalker, Map)} instead. This method could be removed in the next |
There was a problem hiding this comment.
How would QueryPlus.run be implemented without being able to use this method?
There was a problem hiding this comment.
QueryPlus.run() is implemented without using this method for BaseQuery, i. e. for all query types in the Druid repository (all Query impls in the Druid repo extend BaseQuery). QueryPlus.run() falls back to Query.run() only for "unknown" Query implementations in extensions. They should be forced to move to the new API when QueryRunner.run(Query, Map) method is removed in the next major or minor version of Druid.
There was a problem hiding this comment.
What new API will they move to if they don't extend BaseQuery? Would you plan to add another method to Query in a later patch?
There was a problem hiding this comment.
In backwards incompatible patch, Query.run(walker, context) is removed and Query.getRunner(walker, context) could be added. Then QueryPlus.run(walker, context) is implemented as this.query.getRunner(walker, context).run(this, context).
There was a problem hiding this comment.
Could you add a comment describing this plan? Otherwise, anyone reading the code might be confused (like I was) about what the replacement is for this deprecated method that has no obvious replacement.
| * An immutable composite object of {@link Query} + extra stuff needed in {@link QueryRunner}s. This "extra stuff" | ||
| * is only {@link QueryMetrics} yet. | ||
| */ | ||
| public final class QueryPlus<T> |
There was a problem hiding this comment.
If you change this to QueryPlus<T, QueryType extends Query<T>> would that reduce the amount of casting required from getQuery()?
There was a problem hiding this comment.
Since QueryRunner is also parameterized only with T, the parameter of QueryRunner.run() could only be QueryPlus<T, ? extends Query<T>>, so it won't help much. Adding parameter to QueryRunner or run() method makes it too complex.
I think parametrization in this area pretty much doesn't work (but I don't think this is an issue), so I created QueryPlus to have the same parameter as Query and QueryRunner, to keep changes in this PR to minimum.
| */ | ||
| Sequence<T> run(Query<T> query, Map<String, Object> responseContext); | ||
| @Deprecated | ||
| default Sequence<T> run(Query<T> query, Map<String, Object> responseContext) |
There was a problem hiding this comment.
Is anything in Druid still implementing this method, or did you convert them all to QueryPlus?
There was a problem hiding this comment.
No implementations. This method is still called in benchmarks and tests at ~270 places.
|
|
||
| if (QueryContexts.isBySegment(query) || forceChainedExecution) { | ||
| return new ChainedExecutionQueryRunner(exec, queryWatcher, queryables).run(query, responseContext); | ||
| // TODO why query, not queryForRunners? |
There was a problem hiding this comment.
Ah, this should be queryForRunners. I think it won't have an effect in practice (since in this block we're already at the lowest level of the merge -- see comment above) so it's not a "bug". But nevertheless, queryForRunners would make more sense here.
gianm
left a comment
There was a problem hiding this comment.
LGTM, but would appreciate a comment being added along the lines of #4184 (comment).
|
@gianm thanks for quick review! |
| return doRun(baseRunner, QueryPlus.wrap(query), context); | ||
| } | ||
|
|
||
| protected Sequence<T> doRun(QueryRunner<T> baseRunner, QueryPlus<T> queryPlus, Map<String, Object> context) |
There was a problem hiding this comment.
this should be abstract , currently they look like in endless mutual recursion.
There was a problem hiding this comment.
Such recursion is supposed to be broken by subclass who overrides one or both of the methods. The same mutual recursion is added in QueryRunner interface, in this PR.
| * @deprecated override {@link #doRun(QueryRunner, QueryPlus, Map)} instead | ||
| */ | ||
| @Deprecated | ||
| protected Sequence<T> doRun(QueryRunner<T> baseRunner, Query<T> query, Map<String, Object> context) |
There was a problem hiding this comment.
we can remove it , its not part of any public extension
|
@himanshug do you have any other comments? |
drcrallen
left a comment
There was a problem hiding this comment.
Overall looks good. Can you add a unit test showing the behavior you are wishing to preserve, with a javadoc comment on when/If the compatibility could be removed?
Also had a surprising change in the by segment query
| @SuppressWarnings("unchecked") | ||
| final Sequence<Result<BySegmentResultValueClass<T>>> resultSequence = clientQueryable.run( | ||
| bySegmentQuery.withQuerySegmentSpec(segmentSpec), | ||
| queryPlus.withQuerySegmentSpec(segmentSpec), |
There was a problem hiding this comment.
This changed from the by segment query.
There was a problem hiding this comment.
i think its same, bySegmentQuery was just a another name for query, but @leventov can confirm
There was a problem hiding this comment.
yes, bySegmentQuery was just (Query<Result<BySegmentResultValueClass<T>>>) ((Query) query), casting the query reference without changing anything.
There was a problem hiding this comment.
so behavior should still be the same.
|
👍 |
|
@leventov is this still WIP? |
|
@gianm I'm going to add test(s) @drcrallen has asked for |
…moval plans in Druid 0.11 in Javadocs
|
@drcrallen added test and clarified Javadocs |
|
I'm holding off on merge for a few hours to give @cheddar a chance to check it out at a high level. |
|
Looked over the general interfaces and stuff and it looks good to me. The one bit of a rabbit hole I went down is why we are lazily instantiating the QueryMetrics instead of doing it at 👍 |
|
@cheddar thanks. Please merge? |
Add
QueryPlus. AddQueryRunner.run(QueryPlus, Map)method with default implementation, to replaceQueryRunner.run(Query, Map).This PR is a rethink of #4131, designed for backwards compatibility with extensions.
A follow-up of #3954, a part of #3798.