Skip to content

KAFKA-20524: CSV reset offset plan for kafka-share-groups.sh#22197

Open
AndrewJSchofield wants to merge 2 commits intoapache:trunkfrom
AndrewJSchofield:KAFKA-20524
Open

KAFKA-20524: CSV reset offset plan for kafka-share-groups.sh#22197
AndrewJSchofield wants to merge 2 commits intoapache:trunkfrom
AndrewJSchofield:KAFKA-20524

Conversation

@AndrewJSchofield
Copy link
Copy Markdown
Member

@AndrewJSchofield AndrewJSchofield commented May 2, 2026

@github-actions github-actions Bot added the tools label May 2, 2026
@AndrewJSchofield AndrewJSchofield added the KIP-932 Queues for Kafka label May 3, 2026
return offsetsUtils.resetToLatest(partitionsToReset);
} else if (opts.options.has(opts.resetToDatetimeOpt)) {
return offsetsUtils.resetToDateTime(partitionsToReset);
} else if (offsetsUtils.resetPlanFromFile().isPresent()) {
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.

This call resetPlanFromFile and next call resetFromFile seem to do same reading and parsing the entire csv. May be use opts to check for presence?

withTimeoutMs(new ListShareGroupOffsetsOptions())
).partitionsToOffsetInfo(groupId).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
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.

Is it better to interrupt the currentThread for RunTimeException?
For ExecutionException, getting the instance type for ex if it's of KafkaException(GroupAuthorizationException etc), it could be more visible to the caller ?

offsetsUtils.checkAllTopicPartitionsValid(partitionsToReset);
if (opts.options.has(opts.resetToEarliestOpt)) {
if (opts.options.has(opts.resetToOffsetOpt)) {
return offsetsUtils.resetToOffset(partitionsToReset);
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.

Not related to this pr, but this call sets offset to 0L, if opts.resetToOffsetOpt is empty or null. Is that ok instead of throwing an exception?
This is also the same in CosnumerGroupCommand too I think.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think that's a tiny piece of defensive code in OffsetsUtils.resetToOffset. In practice, the command line argument spec for resetToOffsetOpt requires an argument of type Long. If no argument or a non-Long argument is specified with --to-offset, the command does fail.

Copy link
Copy Markdown
Contributor

@muralibasani muralibasani left a comment

Choose a reason for hiding this comment

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

@AndrewJSchofield thanks for the pr. I have some minor comments.

@AndrewJSchofield
Copy link
Copy Markdown
Member Author

@AndrewJSchofield thanks for the pr. I have some minor comments.

Thanks for the review. I basically mapped the consumer group tool options across to the share group tool, and you're quite right that there are a few things to improve. I'll sort it out.

Copy link
Copy Markdown
Member

@chia7712 chia7712 left a comment

Choose a reason for hiding this comment

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

@AndrewJSchofield Out of curiosity, does the KIP's motivation include aligning offset-related options? If so, should we also support the shift-by option?

"To define the scope use --all-topics or --topic." + NL +
"Additionally, the --export option is used to export the offsets in CSV format." + NL +
"You must choose one of the following reset specifications: --to-datetime, --to-earliest, --to-latest, --from-file, --to-current, --to-offset." + NL +
"To define the scope use --all-topics or --topic. One scope must be specified unless you use '--from-file'." + NL +
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

To define the scope use --all-topics or --topic. One scope must be specified unless you use '--from-file'

It looks like we should remove the condition if (!options.has(topicOpt) && !options.has(allTopicsOpt)) from line 226, right?

return preparedOffsetsForPartitionsWithCommittedOffset;
}

public Map<TopicPartition, OffsetAndMetadata> resetToCurrentForShareGroup(Collection<TopicPartition> partitionsToReset, Map<TopicPartition, SharePartitionOffsetInfo> currentOffsetInfo) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I understand this implementation aligns with resetToCurrent, but it feels a bit old-school to me. We could simplify it using the following style

    public Map<TopicPartition, OffsetAndMetadata> resetToCurrentForShareGroup(Collection<TopicPartition> partitionsToReset, Map<TopicPartition, SharePartitionOffsetInfo> currentOffsetInfo) {
        var partitioned = partitionsToReset.stream().collect(Collectors.partitioningBy(currentOffsetInfo::containsKey));
        var partitionsToResetWithStartOffset = partitioned.get(true);
        var partitionsToResetWithoutStartOffset = partitioned.get(false);

        var preparedOffsetsForPartitionsWithStartOffset = partitionsToResetWithStartOffset.stream()
            .collect(Collectors.toMap(Function.identity(), topicPartition -> new OffsetAndMetadata(currentOffsetInfo.get(topicPartition).startOffset())));

        getLogEndOffsets(partitionsToResetWithoutStartOffset).forEach((tp, logOffsetResult) -> {
            if (!(logOffsetResult instanceof OffsetsUtils.LogOffset logOffset)) {
                throw new IllegalStateException("Error getting ending offset of topic partition: " + tp);
            }
            preparedOffsetsForPartitionsWithStartOffset.put(tp, new OffsetAndMetadata(logOffset.value));
        });

        return preparedOffsetsForPartitionsWithStartOffset;
    }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

BTW, I'm fine with addressing this in a separate PR

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This KIP is still in voting and I'm getting the PR ready in anticipation. Entirely happy to iterate on it.

@AndrewJSchofield
Copy link
Copy Markdown
Member Author

@AndrewJSchofield Out of curiosity, does the KIP's motivation include aligning offset-related options? If so, should we also support the shift-by option?

@chia7712 The motivation was really to enable offsets to be exported from one group and used to initialise another. I'm not really averse to shift-by, but hadn't planned to do it. There is also another difference and that is that you can only reset the offsets on one share group at a time. When resetting offsets for consumer groups, you can list multiple groups or reset all groups at once.

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

Labels

KIP-932 Queues for Kafka tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants