Skip to content

Conversation

@hdikeman
Copy link
Contributor

@hdikeman hdikeman commented Nov 25, 2025

Description

Adding a verifier option to retry any queries which were shown to be nondeterministic during determinism analysis.

Motivation and Context

In some cases, fresh data may be landing on the source tables as the verifier is running. e.g., in our case, the source tables have a partition landing between when the control and test query is running. This is not a meaningful difference between source and test query, so we would like to retry those automatically and immediately without performing a retest.

Impact

Verifier runs can now automatically retry queries which failed due to transient nondeterminism.

Test Plan

Added test coverage to TestVerifierConfig + the E2E DataVerificationTest

Contributor checklist

  • Please make sure your submission complies with our contributing guide, in particular code style and commit standards.
  • 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

== NO RELEASE NOTE ==

Differential Revision: D87831484

@hdikeman hdikeman requested a review from a team as a code owner November 25, 2025 17:40
@prestodb-ci prestodb-ci added the from:Meta PR from Meta label Nov 25, 2025
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Nov 25, 2025

Reviewer's Guide

Adds a new verifier config flag and behavior to automatically resubmit nondeterministic query verifications instead of marking them as skipped, plus tests and config wiring.

Sequence diagram for nondeterministic verification resubmission flow

sequenceDiagram
    actor VerifierUser
    participant VerifierCli
    participant VerificationManager
    participant AbstractVerification
    participant DeterminismAnalyzer

    VerifierUser->>VerifierCli: run_verifier_with_optional_flag(resubmit_nondeterministic_queries)
    VerifierCli->>VerificationManager: start_verification_jobs()
    VerificationManager->>AbstractVerification: verify()

    AbstractVerification->>AbstractVerification: run_control_and_test_queries()
    AbstractVerification->>AbstractVerification: compare_results()
    AbstractVerification-->>VerificationManager: MatchResult mismatch_possibly_caused_by_nondeterminism

    VerificationManager->>AbstractVerification: analyze_determinism()
    AbstractVerification->>DeterminismAnalyzer: analyzeDeterminism(control_query_result, test_query_result, match_result)
    DeterminismAnalyzer-->>AbstractVerification: DeterminismAnalysisDetails

    alt resubmitNondeterministicQueries_enabled_and_limit_not_reached
        AbstractVerification->>AbstractVerification: check resubmitNondeterministicQueries
        AbstractVerification->>AbstractVerification: check verificationContext.getResubmissionCount() < verificationResubmissionLimit
        AbstractVerification-->>VerificationManager: VerificationResult(resubmissionRequested = true)
        VerificationManager->>VerificationManager: increment_resubmission_count()
        VerificationManager->>AbstractVerification: verify()  %% resubmitted verification
    else flag_disabled_or_limit_reached
        AbstractVerification-->>VerificationManager: VerificationResult(resubmissionRequested = false)
        VerificationManager-->>VerifierCli: report_nondeterministic_failure()
        VerifierCli-->>VerifierUser: display_nondeterministic_failure()
    end
Loading

Updated class diagram for verifier nondeterministic resubmission configuration

classDiagram
    class VerifierConfig {
        -boolean skipChecksum
        -boolean runDeterminismAnalysisOnTest
        -boolean concurrentControlAndTest
        -boolean resubmitNondeterministicQueries
        +boolean isSkipChecksum()
        +boolean isRunDeterminismAnalysisOnTest()
        +boolean isConcurrentControlAndTest()
        +boolean isResubmitNondeterministicQueries()
        +VerifierConfig setConcurrentControlAndTest(boolean concurrentControlAndTest)
        +VerifierConfig setResubmitNondeterministicQueries(boolean resubmitNondeterministicQueries)
    }

    class AbstractVerification {
        #boolean isExplain
        #boolean isRunDeterminismAnalysisOnTest
        -boolean concurrentControlAndTest
        -boolean resubmitNondeterministicQueries
        -int verificationResubmissionLimit
        +AbstractVerification(VerifierConfig verifierConfig, QueryBundleFactory queryBundleFactory, VerificationContext verificationContext, int verificationResubmissionLimit)
        +VerificationResult verify()
        -DeterminismAnalysisDetails analyzeDeterminism(QueryBundle control, QueryBundle test, MatchResult matchResult)
    }

    class VerificationContext {
        +int getResubmissionCount()
    }

    class VerificationResult {
        +VerificationResult(AbstractVerification verification, boolean resubmissionRequested, Optional determinismAnalysisDetails)
    }

    class MatchResult {
        +boolean isMismatchPossiblyCausedByNonDeterminism()
    }

    class DeterminismAnalysisDetails {
        +DeterminismAnalysis getDeterminismAnalysis()
    }

    class DeterminismAnalysis {
        +boolean isNonDeterministic()
    }

    class QueryBundleFactory
    class QueryBundle

    AbstractVerification --> VerifierConfig : reads_configuration
    AbstractVerification --> VerificationContext : uses_resubmission_count
    AbstractVerification --> VerificationResult : creates
    AbstractVerification --> MatchResult : evaluates
    AbstractVerification --> DeterminismAnalysisDetails : computes
    DeterminismAnalysisDetails --> DeterminismAnalysis : contains
    AbstractVerification --> QueryBundleFactory : creates_bundles
    AbstractVerification --> QueryBundle : uses_in_verification
    VerifierConfig o-- AbstractVerification : provides_flags_and_limits
Loading

File-Level Changes

Change Details Files
Introduce a configuration flag to control automatic resubmission of nondeterministic verifications and wire it through the verifier pipeline.
  • Add resubmitNondeterministicQueries boolean property with config key and description to VerifierConfig and its accessors
  • Propagate resubmitNondeterministicQueries from VerifierConfig into AbstractVerification as a final field
  • Update AbstractVerificationTest.VerificationSettings to include an Optional flag and apply it when building VerifierConfig
  • Extend TestVerifierConfig defaults and explicit property mapping tests to cover the new configuration option
presto-verifier/src/main/java/com/facebook/presto/verifier/framework/VerifierConfig.java
presto-verifier/src/main/java/com/facebook/presto/verifier/framework/AbstractVerification.java
presto-verifier/src/test/java/com/facebook/presto/verifier/framework/AbstractVerificationTest.java
presto-verifier/src/test/java/com/facebook/presto/verifier/framework/TestVerifierConfig.java
Implement the behavior to resubmit verifications when determinism analysis detects nondeterminism within limits.
  • In the verification flow, after determinism analysis indicates possible nondeterminism, check the new flag and the determinism result
  • If enabled, nondeterministic, and under the resubmission limit, short‑circuit by returning a VerificationResult that signals resubmission instead of emitting a final event
presto-verifier/src/main/java/com/facebook/presto/verifier/framework/AbstractVerification.java
Add tests to validate nondeterministic resubmission behavior and configuration mapping.
  • Add TestDataVerification.testNondeterministicResubmission to assert that with the flag set, nondeterministic queries are resubmitted (no final event), and without the flag they are marked SKIPPED with NON_DETERMINISTIC reason
  • Extend AbstractVerificationTest’s VerificationSettings and wiring to support the new option in tests
presto-verifier/src/test/java/com/facebook/presto/verifier/framework/TestDataVerification.java
presto-verifier/src/test/java/com/facebook/presto/verifier/framework/AbstractVerificationTest.java

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • In AbstractVerification, the boolean flag in new VerificationResult(this, true, Optional.empty()) is not self-explanatory in the context of a resubmission path; consider using a factory or named helper to make this code path’s intent (resubmission vs. normal success/failure) clearer to future readers.
  • The @ConfigDescription for resubmit-nondeterministic-queries could be improved by explicitly documenting its interaction with verificationResubmissionLimit so that operators understand when resubmissions will actually occur and when they will stop.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In AbstractVerification, the boolean flag in `new VerificationResult(this, true, Optional.empty())` is not self-explanatory in the context of a resubmission path; consider using a factory or named helper to make this code path’s intent (resubmission vs. normal success/failure) clearer to future readers.
- The `@ConfigDescription` for `resubmit-nondeterministic-queries` could be improved by explicitly documenting its interaction with `verificationResubmissionLimit` so that operators understand when resubmissions will actually occur and when they will stop.

## Individual Comments

### Comment 1
<location> `presto-verifier/src/test/java/com/facebook/presto/verifier/framework/TestDataVerification.java:275-284` </location>
<code_context>
         assertDeterminismAnalysisRun(runs.get(0), true);
     }

+    @Test
+    public void testNondeterministicResubmission()
+    {
+        VerificationSettings settingsWithFlag = new VerificationSettings();
+        settingsWithFlag.resubmitNondeterministicQueries = Optional.of(true);
+
+        Optional<VerifierQueryEvent> eventWithFlag = runVerification("SELECT rand()", "SELECT 2.0", settingsWithFlag);
+        assertFalse(eventWithFlag.isPresent());
+
+        Optional<VerifierQueryEvent> eventWithoutFlag = runVerification("SELECT rand()", "SELECT 2.0");
+        assertTrue(eventWithoutFlag.isPresent());
+        assertEquals(eventWithoutFlag.get().getStatus(), SKIPPED.name());
+        assertEquals(eventWithoutFlag.get().getSkippedReason(), NON_DETERMINISTIC.name());
+    }
+
</code_context>

<issue_to_address>
**issue (testing):** Add tests for resubmission limit and deterministic mismatch cases when resubmitNondeterministicQueries is enabled

Please also cover two important edge cases:

- With resubmitNondeterministicQueries = true but a deterministic mismatch, confirm we do not resubmit and still produce the appropriate SKIPPED/FAILED event.
- With resubmitNondeterministicQueries = true and a nondeterministic mismatch, but the resubmission count already at verificationResubmissionLimit, confirm we do not resubmit again and instead emit a SKIPPED/NON_DETERMINISTIC event.

A small focused test using a low resubmission limit (e.g., 0 or 1) that forces deterministic vs nondeterministic mismatches would validate the new branching in AbstractVerification across these cases.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +275 to +284
@Test
public void testNondeterministicResubmission()
{
VerificationSettings settingsWithFlag = new VerificationSettings();
settingsWithFlag.resubmitNondeterministicQueries = Optional.of(true);

Optional<VerifierQueryEvent> eventWithFlag = runVerification("SELECT rand()", "SELECT 2.0", settingsWithFlag);
assertFalse(eventWithFlag.isPresent());

Optional<VerifierQueryEvent> eventWithoutFlag = runVerification("SELECT rand()", "SELECT 2.0");
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (testing): Add tests for resubmission limit and deterministic mismatch cases when resubmitNondeterministicQueries is enabled

Please also cover two important edge cases:

  • With resubmitNondeterministicQueries = true but a deterministic mismatch, confirm we do not resubmit and still produce the appropriate SKIPPED/FAILED event.
  • With resubmitNondeterministicQueries = true and a nondeterministic mismatch, but the resubmission count already at verificationResubmissionLimit, confirm we do not resubmit again and instead emit a SKIPPED/NON_DETERMINISTIC event.

A small focused test using a low resubmission limit (e.g., 0 or 1) that forces deterministic vs nondeterministic mismatches would validate the new branching in AbstractVerification across these cases.

Copy link
Contributor

@NikhilCollooru NikhilCollooru left a comment

Choose a reason for hiding this comment

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

lgtm

@hdikeman hdikeman changed the title feat(verifier): Add nondeterministic verifier retry feat(testing): Add nondeterministic verifier retry Nov 26, 2025
Summary:

We have a verifier usecase where partitions may still be landing when the verifier is running. If the partition becomes available in between when the control and test query runs, the test is marked nondeterministic but still a failure. We actually aren't interested in this case and don't want to spend manual effort resolving it, we would rather re-run the test immediately in hopes that the nondeterminism goes away (e.g. that partitions don't continue to land). Adding a flag to that effect

There is not currently a mechanism to have an inline retry, so in this diff I am adding an additional CLI option to resubmit queries if determinism analysis has proven them to be nondeterministic

e.g., if fresh data has arrived and altered the results after the control query has run.

Reviewed By: NikhilCollooru

Differential Revision: D87831484
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.

4 participants