Skip to content

Flink: Move write from AppenderFactory to FileWriterFactory - #14271

Merged
pvary merged 2 commits into
apache:mainfrom
pvary:move_to_writer
Oct 14, 2025
Merged

Flink: Move write from AppenderFactory to FileWriterFactory#14271
pvary merged 2 commits into
apache:mainfrom
pvary:move_to_writer

Conversation

@pvary

@pvary pvary commented Oct 7, 2025

Copy link
Copy Markdown
Contributor

@aokolnychyi created the FileWriterFactory interfaces to write Data/PositionDelete/EqualityDelete Iceberg files.
Spark moved to the new API, but Flink never started to use it.

During the FileFormat API discussions some raised the question if we want to take the move now, before migrating to the new API. This PR attempts to do this.

There are 2 main parts:

  • Core: Migrating the BaseTaskWriter to use both FileAppenderFactory and FileWriterFactory whichever is available
  • Data: Add a new writerProperties to the BaseFileWriterFactory, to allow migrating the Flink functionality where the users of the FlinkFileAppenderFactory can provide additional configurations to the appender.
  • Flink: Migrate the BaseDeltaTaskWriter to use the FlinkFileWriterFactory.
  • Flink tests: Migrate the Flink tests to use the FlinkFileWriterFactory.

2 usages for the FlinkAppenderFactory remains:

  • TestFlinkAppenderFactory - obviously we will remove when the deprecation period is finished
  • TestFlinkMergingMetrics - we should move this FileFormat TCK


/** A base writer factory to be extended by query engine integrations. */
public abstract class BaseFileWriterFactory<T> implements FileWriterFactory<T> {
public abstract class BaseFileWriterFactory<T> implements FileWriterFactory<T>, Serializable {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

needed for Flink serialization

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.

Checked the child classes. SparkFileWriterFactory is probably ok, as the Table object was extracted from a broadcast variable for SerializableTable. But GenericFileWriterFactory ma be constructed with a regular and may not be serializable.

Since FlinkFileWriterFactory is already marked as serializable. maybe we don't need this change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Since FlinkFileWriterFactory is already marked as serializable. maybe we don't need this change?

I had test failures. Flink was not able to serialize/deserialize the factory, because the base class was not serializable.

GenericFileWriterFactory ma be constructed with a regular and may not be serializable.

BaseTable implements writeReplace, which makes sure that the table object is always serializable

  Object writeReplace() {
    return SerializableTable.copyOf(this);
  }

Added a test anyways.

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.

ah. I didn't notice that BaseTable implements writeReplace. thanks for explaining

@pvary

pvary commented Oct 7, 2025

Copy link
Copy Markdown
Contributor Author

CC: @stevenzwu, @Guosmilesmile, @mxm

super(spec, format, appenderFactory, fileFactory, io, targetFileSize);
}

protected PartitionedWriter(

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.

looks like PartitionedWriter is not used in Iceberg repo anymore

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it is not changed with this PR.
But, yeah, we might want to deprecate it.

this.targetFileSize = targetFileSize;
}

protected BaseTaskWriter(

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.

I guess this is an approach with minimal effort to move Flink to FileWriterFactory.

Otherwise, the intention is probably for Flink and Kafka to move away from BaseTaskWriter as well. E.g., Spark is using FanoutDataWriter and ClusteredDataWriter.

Should we move Flink to use PartitioningWriter? might be a bigger change though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

What we are missing is the BaseEqualityDeltaWriter - RowDataDeltaWriter which keeps track of the previously written rows and create a position delete if it is deleted again.

This could be done, but I would postpone it to another PR.

This PR would allow us to test the FileFormat API with Flink and also not expose the WriteBuilder on the FormatModelRegistry

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.

I am fine with this approach. It doesn't require a big effort to migrate Flink to FileWriterFactory as an intermediate step, although if-else isn't perfect.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If we deprecate the AppenderFactory then we can remove the if statements.

Comment thread flink/v2.0/flink/src/test/java/org/apache/iceberg/flink/SimpleDataUtil.java Outdated
@apache apache deleted a comment Oct 9, 2025

@stevenzwu stevenzwu 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.

LGTM. just a nit comment on annotations for the public class

import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;

class FlinkFileWriterFactory extends BaseFileWriterFactory<RowData> implements Serializable {
public class FlinkFileWriterFactory extends BaseFileWriterFactory<RowData> implements Serializable {

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.

nit: looks like the public is only needed for SimpleDataUtil and other test class. Should we add @Internal and @VisibleForTest annotations?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As discussed offline, this needs to be public so we can deprecate the FlinkFileAppenderFactory, and users of that could migrate using the new class.

@pvary
pvary merged commit 02fdf38 into apache:main Oct 14, 2025
42 checks passed
@pvary

pvary commented Oct 14, 2025

Copy link
Copy Markdown
Contributor Author

Merged to main.
Thanks for the review @stevenzwu!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants