This is an automated email from the ASF dual-hosted git repository.

MartijnVisser pushed a commit to branch release-2.3
in repository https://gitbox.apache.org/repos/asf/flink.git


The following commit(s) were added to refs/heads/release-2.3 by this push:
     new be19c67322a [FLINK-38534][runtime/tests] Fix LocalRecoveryTest racing 
the async task deployment
be19c67322a is described below

commit be19c67322a77995a01dc800f2921ea745b3ccc4
Author: Martijn Visser <[email protected]>
AuthorDate: Fri Jun 12 12:15:47 2026 +0200

    [FLINK-38534][runtime/tests] Fix LocalRecoveryTest racing the async task 
deployment
    
    The test forces executions to RUNNING while the scheduler is still
    creating task deployment descriptors; deployment is then rejected, the
    job restarts, and the manual checkpoint never registers. Wait for
    descriptor creation before forcing RUNNING, keyed off the descriptor
    future because executions are observable in DEPLOYING before the future
    is assigned. The earlier FLINK-38534 fix waited for RUNNING after the
    forced transition and misses this race.
    
    Generated-by: Claude Opus 4.8 (1M context)
    (cherry picked from commit e009616411c127c36d95ba38a7edb66c22eda62f)
---
 .../runtime/scheduler/SchedulerTestingUtils.java   | 32 ++++++++++++++++++++++
 .../scheduler/adaptive/LocalRecoveryTest.java      | 16 +++++++----
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git 
a/flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/SchedulerTestingUtils.java
 
b/flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/SchedulerTestingUtils.java
index 49a81d6fd2d..1257f5a1285 100644
--- 
a/flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/SchedulerTestingUtils.java
+++ 
b/flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/SchedulerTestingUtils.java
@@ -362,6 +362,38 @@ public class SchedulerTestingUtils {
                 RETRY_ATTEMPTS);
     }
 
+    /**
+     * Waits until the task deployment descriptor of every current execution 
has been created. Call
+     * this before forcing executions into a later state; deployment is 
rejected once an execution
+     * leaves DEPLOYING.
+     *
+     * <p>Unlike {@code 
ExecutionUtils#waitForTaskDeploymentDescriptorsCreation}, this may run
+     * concurrently with {@code Execution.deploy()}: executions are observable 
in DEPLOYING before
+     * the descriptor future is assigned, so the {@code IllegalStateException} 
thrown while the
+     * future is unset is treated as "not yet ready".
+     *
+     * @param executionGraph the ExecutionGraph to wait for
+     * @throws Exception if the condition is not met within the timeout period
+     */
+    public static void waitForAllTasksDeploymentDescriptorsCreated(
+            final ExecutionGraph executionGraph) throws Exception {
+        for (ExecutionVertex vertex : 
executionGraph.getAllExecutionVertices()) {
+            waitUntilCondition(
+                    () -> {
+                        try {
+                            vertex.getCurrentExecutionAttempt()
+                                    .getTddCreationDuringDeployFuture()
+                                    .join();
+                            return true;
+                        } catch (IllegalStateException 
deploymentNotStartedYet) {
+                            return false;
+                        }
+                    },
+                    RETRY_INTERVAL_MILLIS,
+                    RETRY_ATTEMPTS);
+        }
+    }
+
     private static ExecutionJobVertex getJobVertex(
             DefaultScheduler scheduler, JobVertexID jobVertexId) {
         final ExecutionVertexID id = new ExecutionVertexID(jobVertexId, 0);
diff --git 
a/flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/adaptive/LocalRecoveryTest.java
 
b/flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/adaptive/LocalRecoveryTest.java
index bdaf69c3f31..4227afa3bf3 100644
--- 
a/flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/adaptive/LocalRecoveryTest.java
+++ 
b/flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/adaptive/LocalRecoveryTest.java
@@ -56,6 +56,7 @@ import java.util.stream.Collectors;
 import static 
org.apache.flink.runtime.checkpoint.CheckpointCoordinatorTestingUtils.generateKeyGroupState;
 import static 
org.apache.flink.runtime.scheduler.SchedulerTestingUtils.acknowledgePendingCheckpoint;
 import static 
org.apache.flink.runtime.scheduler.SchedulerTestingUtils.setAllExecutionsToRunning;
+import static 
org.apache.flink.runtime.scheduler.SchedulerTestingUtils.waitForAllTasksDeploymentDescriptorsCreated;
 import static 
org.apache.flink.runtime.scheduler.SchedulerTestingUtils.waitForAllTasksRunning;
 import static 
org.apache.flink.runtime.scheduler.SchedulerTestingUtils.waitForCheckpointInProgress;
 import static 
org.apache.flink.runtime.scheduler.SchedulerTestingUtils.waitForCompletedCheckpoint;
@@ -103,11 +104,6 @@ public class LocalRecoveryTest extends 
AdaptiveSchedulerTestBase {
 
         // Transition job and all subtasks to RUNNING state.
         waitForJobStatusRunning(scheduler);
-        runInMainThread(() -> setAllExecutionsToRunning(scheduler));
-        // Wait for all task executions to actually reach RUNNING state before 
triggering
-        // checkpoint.
-        // In slower CI environments, state transitions may not complete 
immediately, causing
-        // checkpoint triggers to be rejected if tasks are still in 
DEPLOYING/INITIALIZING state.
         final ExecutionGraph executionGraph =
                 scheduler
                         .getState()
@@ -115,6 +111,16 @@ public class LocalRecoveryTest extends 
AdaptiveSchedulerTestBase {
                         .map(StateWithExecutionGraph::getExecutionGraph)
                         .orElseThrow(
                                 () -> new 
IllegalStateException("ExecutionGraph not available"));
+
+        // Forcing RUNNING while the asynchronous descriptor creation is still 
in flight fails the
+        // deployment and restarts the job, so the checkpoint below would 
never register.
+        waitForAllTasksDeploymentDescriptorsCreated(executionGraph);
+
+        runInMainThread(() -> setAllExecutionsToRunning(scheduler));
+        // Wait for all task executions to actually reach RUNNING state before 
triggering
+        // checkpoint.
+        // In slower CI environments, state transitions may not complete 
immediately, causing
+        // checkpoint triggers to be rejected if tasks are still in 
DEPLOYING/INITIALIZING state.
         waitForAllTasksRunning(executionGraph);
 
         // Trigger a checkpoint

Reply via email to