Skip to content

[test] Stabilize SinkSavepointITCase.testRecoverFromSavepoint - #8741

Merged
JingsongLi merged 1 commit into
apache:masterfrom
wombatu-kun:flink/honor-timeout-sink-savepoint-it
Jul 20, 2026
Merged

[test] Stabilize SinkSavepointITCase.testRecoverFromSavepoint#8741
JingsongLi merged 1 commit into
apache:masterfrom
wombatu-kun:flink/honor-timeout-sink-savepoint-it

Conversation

@wombatu-kun

Copy link
Copy Markdown
Contributor

Purpose

SinkSavepointITCase.testRecoverFromSavepoint intermittently hangs an entire CI job instead of failing within its own budget. For example the "UTCase and ITCase Flink 2.x on JDK 11" job at https://github.com/apache/paimon/actions/runs/29686582857/job/88191764951 (which surfaced while validating #8736) ran the full 2h workflow cap and was cancelled; this test was the only class that logged Running ... and never reported completion.

Two independent problems compound.

First, the retry loop wraps jobClient.stopWithSavepoint(...).get() in a broad catch (Exception e). JUnit 5 enforces @Timeout(180) in SAME_THREAD mode by delivering a single interrupt to the test thread; when that interrupt lands inside Future.get() it surfaces as InterruptedException, which the broad catch swallowed. The interrupt flag is then cleared and no further interrupt is ever scheduled, so @Timeout(180) was permanently defeated and the test looped until the 2h job-level cap rather than failing at 180s. The catch now rethrows when the exception carries an InterruptedException, so the deadline fires as intended, with a stack that points at where the test is stuck.

Second, the outer loop restarted the job from a savepoint until it reached FINISHED, with no bound on the number of cycles. Each cycle pays a full Flink job-startup plus restore cost, so on a starved runner (the same run had LookupJoinITCase take about 30 minutes) the number of cycles needed to drain the input can explode and legitimately exceed the timeout. The number of stop-with-savepoint / restore cycles is now capped; after that the job is allowed to run to completion uninterrupted, which keeps total runtime bounded while still exercising savepoint recovery. The final wait also fails fast if the job reaches a terminal state without finishing, so a dead job is reported clearly instead of as an opaque timeout.

This is a test-only change; no production code is touched.

Tests

SinkSavepointITCase.testRecoverFromSavepoint (the modified test itself).

testRecoverFromSavepoint intermittently hangs a whole CI job instead of failing within its own budget. For example the "UTCase and ITCase Flink 2.x on JDK 11" run https://github.com/apache/paimon/actions/runs/29686582857/job/88191764951 (surfaced while validating apache#8736) ran the full 2h workflow cap and was cancelled, with this test the only class that started and never reported completion.

Two independent problems compound.

First, the retry loop wraps jobClient.stopWithSavepoint(...).get() in a broad catch (Exception e). JUnit 5 enforces @timeout(180) in SAME_THREAD mode by delivering a single interrupt to the test thread; when that interrupt lands in Future.get() it surfaces as InterruptedException, which the broad catch swallowed. The interrupt flag is then cleared and no further interrupt is ever scheduled, so @timeout(180) was permanently defeated and the test looped until the 2h job-level cap rather than failing at 180s. The catch now rethrows when the exception carries an InterruptedException, so the deadline fires as intended with a diagnosable stack.

Second, the outer loop restarted the job from a savepoint until it reached FINISHED, with no bound on the number of cycles. Each cycle pays a full Flink job-startup plus restore cost, so on a starved runner (the same run had LookupJoinITCase take 30 minutes) the number of cycles needed to drain the input can explode and legitimately exceed the timeout. The number of stop-with-savepoint / restore cycles is now capped; after that the job is allowed to run to completion uninterrupted, which keeps total runtime bounded while still exercising savepoint recovery. The final wait also fails fast if the job reaches a terminal state without finishing, so a dead job is reported clearly instead of as an opaque timeout.

Test-only change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@JingsongLi

Copy link
Copy Markdown
Contributor

+1

@JingsongLi
JingsongLi merged commit 7c93b03 into apache:master Jul 20, 2026
12 checks passed
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