K Nunes
10/28/2025, 12:16 PMDeltaSinkInternal implements Sink<IN> and has these methods:
public Optional<Committer<T>> createCommitter() throws IOException
public Optional<SimpleVersionedSerializer<T>> getCommittableSerializer()
The framework discovers and invokes createWriter() perfectly, but createCommitter() is never called. When I tried adding @Override, I got a compilation error saying these methods aren't part of the Sink<IN> interface.
The Question:
How does a Sink expose its Committer in Flink 2.0? Is there a marker interface I'm missing? How does FileSink do it?
I suspect there's a specific pattern or interface (maybe something that replaced TwoPhaseCommittingSink from 1.x) that I need to implement, but I can't find documentation about it.
Related:
• Delta Lake issue: https://github.com/delta-io/delta/issues/5228
• My implementation branch: https://github.com/kdsnunes/delta/tree/flink/add-flink-2.0-support
• (I'm also trying to get access to Flink's Jira to create an issue there, but it's pending approval)
Any pointers would be super appreciated! Has anyone migrated a connector with Committer support to 2.0?
Thanks in advance! 🙏Arvid Heise
11/03/2025, 7:19 AMSupportsCommitterK Nunes
11/10/2025, 1:47 AMK Nunes
11/10/2025, 1:56 AMChecksum error: delta_log/00000000000000000001.json
exp: -2003856348 got: -1473006609
In Flink 1.x, this was handled by GlobalCommitter (parallelism=1), ensuring atomic commits per checkpoint.
Since GlobalCommitter was removed in Flink 2.0, what’s the recommended way to make sure only one Committer performs a coordinated action like writing to a shared transaction log?
Should this be done via a new built-in pattern, or do we now need custom coordination logic (e.g. distributed lock or barrier)?
Branch: flink/add-flink-2.0-support
Original issue: #5228K Nunes
11/10/2025, 2:37 AMTaskInfo.getIndexOfThisSubtask() to designate one coordinator, or is there a better pattern?Arvid Heise
11/10/2025, 7:05 AMprivate static class TestSinkV2WithPostCommitTopology<InputT>
extends TestSinkV2TwoPhaseCommittingSink<InputT>
implements SupportsPostCommitTopology<String> {
public TestSinkV2WithPostCommitTopology(
DefaultSinkWriter<InputT> writer,
SimpleVersionedSerializer<String> committableSerializer,
DefaultCommitter committer) {
super(writer, committableSerializer, committer);
}
@Override
public void addPostCommitTopology(DataStream<CommittableMessage<String>> committables) {
StandardSinkTopologies.addGlobalCommitter(
committables, DefaultCommitter::new, this::getCommittableSerializer);
}
}
So you add a post commit topology and can do whatever you want, in particular you can use something that simulates the old global committer.K Nunes
11/10/2025, 4:44 PMSupportsPostCommitTopology and StandardSinkTopologies.addGlobalCommitter!
That was exactly what I needed.
I've successfully implemented the pattern and the global coordination is now working correctly - committables from all parallel DeltaCommitter instances are being aggregated and committed atomically
to the Delta Log through the post-commit topology.
The migration from GlobalCommitter to this new pattern is much clearer now. Really appreciate the help! 🙏Nicholas Erasmus
11/25/2025, 3:16 PM