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

[WIP] Add SPI for custom plan checker and plugin for native plan validation #23596

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

BryanCutler
Copy link

Description

This adds a new SPI to create a custom plan checker that will integrate with the built-in plan checkers to validate plans at intermediate, final and fragmented stages. A new plugin is added that provides a native plan checker that will send a plan fragment to the native sidecar where it is validated by performing a conversion to a Velox plan.

A new endpoint is added to the native worker to accept the plan node fragment and return an ok response if the conversion is successful and an error response if failed. The plugin has a configuration to fail the query by throwing an exception on an error, or only log the failure and continue.

In order to allow the query to fail fast, before execution begins, an optional system setting configuration is added that will eagerly build the plan async, so validation can be done early and the query can be removed from the queue without taking up worker resources.

RFC for this addition has been discussed and merged at https://github.com/prestodb/rfcs/blob/main/RFC-0008-plan-checker.md

Motivation and Context

This is a useful addition to help fail queries that are incompatible with Velox before execution begins and cluster resources have been allocated.

Impact

Adds an SPI for a custom plan checker.

Test Plan

Added unit tests for Java and C++, as well as manual testing of queries that currently fail on a native worker.

Contributor checklist

  • Please make sure your submission complies with our development, formatting, commit message, and attribution guidelines.
  • PR description addresses the issue accurately and concisely. If the change is non-trivial, a GitHub Issue is referenced.
  • Documented new properties (with its default value), SQL syntax, functions, or other functionality.
  • If release notes are required, they follow the release notes guidelines.
  • Adequate tests were added if applicable.
  • CI passed.

Release Notes

Please follow release notes guidelines and fill in the release notes below.

== RELEASE NOTES ==

General Changes
* ... :pr:`12345`
* ... :pr:`12345`

Hive Connector Changes
* ... :pr:`12345`
* ... :pr:`12345`

If release note is NOT required, use:

== NO RELEASE NOTE ==

Copy link

linux-foundation-easycla bot commented Sep 6, 2024

CLA Signed

The committers listed above are authorized under a signed CLA.

@BryanCutler
Copy link
Author

Making this PR a draft as recent discussions will likely require a change to send the PlanFragment instead of only the PlanNode portion, and the response from the native endpoint would be more useful to also return the converted Velox plan.

cc @tdcmeehan @rschlussel

@BryanCutler
Copy link
Author

I have separated out the first part of this, adding the session property to enable building and validating the plan eagerly at #23649

Copy link
Contributor

@tdcmeehan tdcmeehan left a comment

Choose a reason for hiding this comment

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

[Changes to SPI to support custom PlanChecker](https://github.com/prestodb/presto/pull/23596/commits/27b0c2ef2b4758de723712d8ad0cc142d9757b02)

Copy link
Contributor

@tdcmeehan tdcmeehan left a comment

Choose a reason for hiding this comment

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

Changes to Java Presto main and server to support custom PlanChecker SPI

@@ -371,6 +377,8 @@ else if (serverConfig.isCoordinator()) {
driftClientBinder(binder).bindDriftClient(ThriftServerInfoClient.class, ForNodeManager.class)
.withAddressSelector(((addressSelectorBinder, annotation, prefix) ->
addressSelectorBinder.bind(AddressSelector.class).annotatedWith(annotation).to(FixedAddressSelector.class)));
// NodeManager instance for plugins to use
binder.bind(NodeManager.class).to(ConnectorAwareNodeManager.class).in(Scopes.SINGLETON);
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than inject this, I would just construct it where needed.

Comment on lines +38 to +39
private Multimap<Stage, Checker> checkers;
private boolean providedInitialized;
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's do the following:

  1. Let's make checkers volatile. This will be accessed in a multithreaded environment, and the volatile keyword will ensure visibility after updates across multiple threads.
  2. Let's remove providedInitialized, and instead add a method update which takes in a PlanCheckerProvider, which is called by the PlanCheckerProviderManager once the manager is initialized.
  3. Now that the flow of communication is reversed, we don't need ensureProvidedInitialized.
  4. Add a @GuardedBy("this") to the class to document the synchronization of this class.

properties = Collections.unmodifiableMap(new HashMap<>(loadProperties(PLAN_CHECKER_PROVIDER_CONFIG)));
}
else {
properties = Collections.emptyMap();
Copy link
Contributor

Choose a reason for hiding this comment

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

ImmutableMap.of()

Copy link
Contributor

@tdcmeehan tdcmeehan left a comment

Choose a reason for hiding this comment

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

Add plan checker provider and plugin for NativePlanChecker

</dependency>

<dependency>
<groupId>org.mockito</groupId>
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't use Mockito in the project. I'll update our development guidelines, but can you create the mocks by hand?

Comment on lines +99 to +101
else if (LOG.isDebugEnabled()) {
LOG.debug("Skipping Native Plan Validation for plan fragment id: %s", planFragment.getId());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I would remove LOG.isDebugEnabled

}
}
catch (final PrestoException e) {
if (config.isQueryFailOnError()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the use case for not failing?

Comment on lines +54 to +55
private static final String PRESTO_SYSTEM_PROPERTY = "X-Presto-System-Property";
private static final String PRESTO_CATALOG_PROPERTY = "X-Presto-Catalog-Property";
Copy link
Contributor

Choose a reason for hiding this comment

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

Unused

Comment on lines +48 to +49
Collections.singletonList(new NativePlanChecker(nodeManager, planFragmentJsonCodec, config)) :
Collections.emptyList();
Copy link
Contributor

Choose a reason for hiding this comment

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

Use ImmutableList


// Create static taskId and empty TableWriteInfo needed for plan conversion
protocol::TaskId taskId = "velox-plan-conversion.0.0.0";
auto tableWriteInfo = std::make_shared<protocol::TableWriteInfo>();
Copy link
Author

Choose a reason for hiding this comment

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

TODO: this causes a problem for create table, need to address

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants