Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor into Writer and Committer #234

Merged
merged 12 commits into from
Apr 25, 2024
Merged

Conversation

fqtab
Copy link
Contributor

@fqtab fqtab commented Apr 9, 2024

Changes summary:

  • Add Writer and Committer interface
  • Refactor existing logic to conform to the above interfaces

There should be no breaking changes in this PR.

@fqtab fqtab marked this pull request as ready for review April 9, 2024 12:43
Copy link
Contributor Author

@fqtab fqtab left a comment

Choose a reason for hiding this comment

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

Still have to figure out why integration tests are failing in CI (passing on my local machine) but in the meantime,
Some comments to hopefully guide reviewers.

Comment on lines 40 to 42
private Writer writer;
private Committer committer;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved pretty much all of the logic out of this IcebergSinkTask class into Writer and Committer implementations. All we do here now is manage the lifecycle of a Writer and Committer.

This will make it easier in the future to introduce a pluggable Committer interface.

Comment on lines 21 to 23
public interface Committer {
void commit(CommittableSupplier committableSupplier);
}
Copy link
Contributor Author

@fqtab fqtab Apr 9, 2024

Choose a reason for hiding this comment

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

This is the Committer interface I'm proposing.
I am not making this interface pluggable in this PR, nor do I intend to do so any time soon until the need arises.
This means we can still change it after this PR without having to do a breaking release.
So we don't need to get this interface 100% right here but we should at least try to align directionally on the design of the interface.


As far as the design is concerned, I've taken some inspiration from Flink here (they have a concept of a Committable as well).

Besides that, I've decided to go super simple with the API for now; just a single void commit(CommittableSupplier committableSupplier) method.

You might wonder, why not just void commit(Committable committable)?
The reason is because we want to let Committer implementations decide when to force the writers to flush and produce a Committable which by definition means closing all open files. We want to avoid closing files unnecessarily because that will result in many small files. Hence the Committer takes a CommittableSuppler and when the Committer determines it is a good time to commit, it can call CommittableSupplier.committables to force the Writer to close any open files and produce a Committable.

Copy link
Contributor

Choose a reason for hiding this comment

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

What is the purpose of having a pluggable committer interface?

Copy link
Contributor

Choose a reason for hiding this comment

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

Answered offline.

Comment on lines -162 to -164
public void flush(Map<TopicPartition, OffsetAndMetadata> currentOffsets) {
processControlEvents();
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the flush method entirely.
All the work now happens in put.

Comment on lines 92 to 82
public Map<TopicPartition, OffsetAndMetadata> preCommit(
Map<TopicPartition, OffsetAndMetadata> currentOffsets) {
return ImmutableMap.of();
Copy link
Contributor Author

@fqtab fqtab Apr 9, 2024

Choose a reason for hiding this comment

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

Not committing to the connect consumer group via this method anymore, all consumer-offset-commits are managed manually.

Comment on lines 225 to 218
KafkaUtils.commitOffsets(
producer, offsetsToCommit, new ConsumerGroupMetadata(config.connectGroupId()));
Copy link
Contributor Author

@fqtab fqtab Apr 9, 2024

Choose a reason for hiding this comment

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

This is where I commit to the connect- group now.
Right next to where I commit to the (current) source-of-truth group: control-group-id.
Note that committing to the connect- group is best-effort (same as before); the connect group is not currently the source of truth.
In a future PR, we will start committing to the connect- group exclusively (as part of worker zombie fencing) and make that the source of truth, however that is a breaking change which I want to avoid in this PR (we should bundle up breaking changes in another PR).

Copy link
Contributor

Choose a reason for hiding this comment

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

Re; future PR, if we stop committing to connect- won't we run into the potential for the connect- consumer group to be deleted by Kafka due to inactivity?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you've misunderstood. In the future, we will still be committing to the connect- consumer group. The only change is that we will be committing to the connect- group exclusively i.e. I intend to get rid of the connector-managed-consumer-group (but this is all theoretical right now, we can talk about it more when we get there).

Comment on lines 298 to 300
public Integer taskId() {
// this is for internal use and is not part of the config definition...
return originalProps.get(INTERNAL_TRANSACTIONAL_SUFFIX_PROP);
return Integer.valueOf(originalProps.get(INTERNAL_TASK_ID));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Another change I do not consider breaking as it's clearly documented as internal.

Comment on lines 33 to 34
// TODO: why putIfAbsent? why not just put?
consumerProps.putIfAbsent(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure I understand why this is a putIfAbsent rather than just put
I'd like to know why.
To me, the most correct thing here is to always start from latest.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm with you, I can't think of a good reason why you would set this to earliest. All this is doing is leaving it to be user configurable w/ a default to latest. Can live with it if we can't figure out the mystery.

@fqtab fqtab mentioned this pull request Apr 9, 2024
thread.start();
LOG.info("Started commit coordinator");
} else {
thread = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Won't this branch result in a case where we have no coordinator thread running?

Are we making the assumption that we are no stable, therefor we are going to be rebalanced, but are assuming we are going to be eventually stable and we'll (eventually) not enter this branch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Won't this branch result in a case where we have no coordinator thread running?

Yes, this is what is happening in the code today.

Are we making the assumption that we are no stable, therefor we are going to be rebalanced, but are assuming we are going to be eventually stable and we'll (eventually) not enter this branch?

This is my understanding.
@bryanck would appreciate it you could confirm if this is why you had this logic?

Copy link
Contributor

Choose a reason for hiding this comment

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

The reasoning for this was to ensure we account for all subscribed topics before ordering for the leader election., e.g. if you have multiple source topics.

@tabmatfournier
Copy link
Contributor

Mostly questions. The main thrust of this is 👍 .

@fqtab
Copy link
Contributor Author

fqtab commented Apr 11, 2024

@bryanck here's the refactor PR I mentioned earlier to enable a pluggable committer interface.
Would be good to get your thoughts/alignment on this before moving forward with the donation process :)

@fqtab fqtab force-pushed the refactor_writer_commiter_interface branch 3 times, most recently from e82981c to 375bc15 Compare April 17, 2024 12:50
@fqtab fqtab force-pushed the refactor_writer_commiter_interface branch from 375bc15 to 1bd2488 Compare April 18, 2024 13:51
Copy link
Contributor

@tabmatfournier tabmatfournier left a comment

Choose a reason for hiding this comment

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

LGTM from my end.

@fqtab fqtab merged commit e3dee36 into main Apr 25, 2024
1 check passed
@fqtab fqtab deleted the refactor_writer_commiter_interface branch April 25, 2024 13:20
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.

None yet

4 participants