Skip to content

Flink: Do not drop IcebergSink commits after a stateless restart - #18123

Open
Beutlin wants to merge 2 commits into
apache:mainfrom
Beutlin:flink-stateless-restart-commit-drop
Open

Beutlin wants to merge 2 commits into
apache:mainfrom
Beutlin:flink-stateless-restart-commit-drop

Conversation

@Beutlin

@Beutlin Beutlin commented Sep 15, 2026

Copy link
Copy Markdown

IcebergCommitter#commit unconditionally looked up
flink.max-committed-checkpoint-id for the incoming committable's jobId-operatorId pair. On a stateless restart the checkpoint counter starts over from 1 while the table still carries the previous run's higher watermark for that same pair, so every new committable was marked as already committed and silently dropped without producing a snapshot.

Gate the lookup on whether the committer actually restored state, mirroring the isRestored() check already used by the legacy IcebergFilesCommitter. On a stateless start there is no restored Flink state and therefore no possibility of a redelivered committable, so every committable can be committed unconditionally.

This change was drafted with AI assistance and verified by running the existing and new IcebergCommitter tests, plus a manual regression check confirming the new tests fail without the fix.

@github-actions github-actions Bot added the flink label Sep 15, 2026

@Guosmilesmile Guosmilesmile left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for your PR! Could we fix the CI errors first?

public class SinkUtil {

private static final long INITIAL_CHECKPOINT_ID = -1L;
public static final long INITIAL_CHECKPOINT_ID = -1L;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

package ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done

IcebergCommitter#commit unconditionally looked up
flink.max-committed-checkpoint-id for the incoming committable's
jobId-operatorId pair. On a stateless restart the checkpoint counter
starts over from 1 while the table still carries the previous run's
higher watermark for that same pair, so every new committable was
marked as already committed and silently dropped without producing a
snapshot.

Gate the lookup on whether the committer actually restored state,
mirroring the isRestored() check already used by the legacy
IcebergFilesCommitter. On a stateless start there is no restored
Flink state and therefore no possibility of a redelivered committable,
so every committable can be committed unconditionally.

This change was drafted with AI assistance and verified by running the
existing and new IcebergCommitter tests, plus a manual regression
check confirming the new tests fail without the fix.
Restrict SinkUtil.INITIAL_CHECKPOINT_ID back to package-private visibility,
since it is only used within org.apache.iceberg.flink.sink.

Rework testCommitTxnAfterStatelessRestart to exercise the real
IcebergSink/CommitterOperatorFactory pipeline via test harnesses instead of
constructing IcebergCommitter directly with a manually supplied `restored`
argument, so the test verifies that IcebergSink#createCommitter derives
`restored` correctly from the operator's actual (non-)restored state.
@Beutlin
Beutlin force-pushed the flink-stateless-restart-commit-drop branch from 6a58e12 to 069515a Compare September 16, 2026 09:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants