Skip to content

Refactor QueryRunner to accept QueryPlus: Query + QueryMetrics (part of #3798)#4184

Merged
drcrallen merged 9 commits intoapache:masterfrom
metamx:queryRunner-accept-queryPlus
May 10, 2017
Merged

Refactor QueryRunner to accept QueryPlus: Query + QueryMetrics (part of #3798)#4184
drcrallen merged 9 commits intoapache:masterfrom
metamx:queryRunner-accept-queryPlus

Conversation

@leventov
Copy link
Copy Markdown
Member

@leventov leventov commented Apr 19, 2017

Add QueryPlus. Add QueryRunner.run(QueryPlus, Map) method with default implementation, to replace QueryRunner.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.

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

Choose a reason for hiding this comment

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

Why is this here instead of letting BaseQuery do it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It means that Query and BaseQuery should learn about QueryPlus, that I didn't want to happen.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

Choose a reason for hiding this comment

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

How would QueryPlus.run be implemented without being able to use this method?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added

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

Choose a reason for hiding this comment

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

If you change this to QueryPlus<T, QueryType extends Query<T>> would that reduce the amount of casting required from getQuery()?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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

Choose a reason for hiding this comment

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

Is anything in Druid still implementing this method, or did you convert them all to QueryPlus?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed

Copy link
Copy Markdown
Contributor

@gianm gianm left a comment

Choose a reason for hiding this comment

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

LGTM, but would appreciate a comment being added along the lines of #4184 (comment).

@leventov
Copy link
Copy Markdown
Member Author

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

Choose a reason for hiding this comment

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

this should be abstract , currently they look like in endless mutual recursion.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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

Choose a reason for hiding this comment

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

we can remove it , its not part of any public extension

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed

@leventov
Copy link
Copy Markdown
Member Author

leventov commented May 4, 2017

@himanshug do you have any other comments?

Copy link
Copy Markdown
Contributor

@drcrallen drcrallen left a comment

Choose a reason for hiding this comment

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

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

Choose a reason for hiding this comment

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

This changed from the by segment query.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

i think its same, bySegmentQuery was just a another name for query, but @leventov can confirm

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yes, bySegmentQuery was just (Query<Result<BySegmentResultValueClass<T>>>) ((Query) query), casting the query reference without changing anything.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

so behavior should still be the same.

@himanshug
Copy link
Copy Markdown
Contributor

👍

@leventov leventov added the WIP label May 5, 2017
@gianm
Copy link
Copy Markdown
Contributor

gianm commented May 7, 2017

@leventov is this still WIP?

@leventov
Copy link
Copy Markdown
Member Author

leventov commented May 7, 2017

@gianm I'm going to add test(s) @drcrallen has asked for

@leventov leventov removed the WIP label May 8, 2017
@leventov
Copy link
Copy Markdown
Member Author

leventov commented May 8, 2017

@drcrallen added test and clarified Javadocs

Copy link
Copy Markdown
Contributor

@drcrallen drcrallen left a comment

Choose a reason for hiding this comment

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

Thanks!

@drcrallen
Copy link
Copy Markdown
Contributor

I'm holding off on merge for a few hours to give @cheddar a chance to check it out at a high level.

@cheddar
Copy link
Copy Markdown
Contributor

cheddar commented May 10, 2017

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 wrap, which was clearly because we need the Toolchest. That then got me thinking that it might be nice to actually attach the Toolchest to QueryPlus at some point as well.

👍

@leventov
Copy link
Copy Markdown
Member Author

@cheddar thanks. Please merge?

@drcrallen drcrallen merged commit e09e892 into apache:master May 10, 2017
@drcrallen drcrallen deleted the queryRunner-accept-queryPlus branch May 10, 2017 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants