MartijnVisser commented on code in PR #28645:
URL: https://github.com/apache/flink/pull/28645#discussion_r3534924591


##########
flink-runtime/src/test/java/org/apache/flink/runtime/scheduler/adaptive/timeline/RescaleTimelineITCase.java:
##########
@@ -567,7 +567,21 @@ void 
testRecordNonTerminatedRescaleMergingWithNewRecoverableFailureTriggerCause(
 
         miniCluster.terminateTaskManager(0);
 
-        waitForVertexParallelismReachedAndJobRunning(jobGraph, JOB_VERTEX_ID, 
PARALLELISM);
+        // A parallelism/running wait cannot synchronize with the failover 
here: it is satisfied
+        // immediately by the stale pre-failover state, and the post-failover 
job runs at a lower
+        // parallelism. Instead, wait until the failover has been merged into 
the in-progress
+        // rescale before snapshotting. Guarded by if (not assumeThat) because 
the disabled-history
+        // leg records nothing and must still assert an empty history below.
+        if (enabledRescaleHistory(configuration)) {
+            waitUntilConditionWithTimeout(
+                    () -> {
+                        List<Rescale> rescaleHistory = 
getRescaleHistory(miniCluster, jobGraph);
+                        return rescaleHistory.size() == 2
+                                && rescaleHistory.get(0).getTriggerCause()
+                                        == TriggerCause.RECOVERABLE_FAILOVER;

Review Comment:
   Thanks for taking a look! I agree with the general principle, but in this 
specific case the size check alone cannot synchronize with the failover, 
because the merge does not append a history entry:
   
   - The history is already at size 2 before the TaskManager is terminated: 
`Created#onEnter` records the initial rescale, and 
`AdaptiveScheduler#recordRescaleForNewResourceRequirements` (called 
synchronously while processing `updateJobResourceRequirements`) terminates it 
and adds the in-progress `UPDATE_REQUIREMENT` rescale via `newRescale(true)`. 
That is also what `testRecordInProgressRescale` asserts, with no failover 
involved.
   - The failover then takes the `!rescaleTimeline.isIdling()` branch in 
`AdaptiveScheduler#recordRescaleForJobRestarting`, which only calls 
`updateRescale(...)`. In `DefaultRescaleTimeline`, `updateRescale` mutates 
`currentRescale`, the same object already held by the history queue; 
`newRescale` is the only method that appends. So the merge re-stamps the 
trigger cause of the existing entry and the size stays 2 throughout.
   
   The original CI failure shows exactly that intermediate state: `hasSize(2)` 
passed while the trigger cause was still `UPDATE_REQUIREMENT`. So a size-only 
wait is satisfied immediately in the pre-merge state and we would re-introduce 
the race this PR fixes. The trigger-cause re-stamp is the only externally 
observable signal that the merge happened.
   
   On the "wait forever" concern: together with your second suggestion (very 
long timeout), a genuine regression in the trigger cause would stall in this 
wait until the CI timeout, which then produces the thread dump you mentioned, 
and the logs would be missing the scheduler's "Merge the current non-terminated 
rescale..." INFO line, which makes the failure diagnosable. I think that is an 
acceptable trade-off given the merge is an in-place mutation with no other 
signal to wait on. WDYT?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to