Skip to content
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,14 @@ public Map<TopicPartition, List<ConsumerRecord<K, V>>> fetchedRecords() {

for (PartitionRecords<K, V> part : this.records) {
if (!subscriptions.isFetchable(part.partition)) {

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 think we still need this check. There may be a rebalance between the time a fetch response is handled and the time it is returned to the user.

log.debug("Ignoring fetched records for {} since it is no longer fetchable", part.partition);
// this can happen when a rebalance happened or a partition consumption paused
// before fetched records are returned to the consumer's poll call
log.debug("Not returning fetched records for partition {} since it is no longer fetchable", part.partition);

// we also need to reset the fetch positions to pretend we did not fetch
// this partition in the previous request at all
subscriptions.fetched(part.partition, part.records.get(0).offset());

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.

Isn't it a little dangerous to assume that the fetch position in the returned record is still relevant? Suppose we have the following sequence:

  1. User calls poll() and we initiate a fetch.
  2. User calls commitSync() (or some other blocking operation) and the fetch returns.
  3. User calls seek() with a new offset.
  4. User calls poll() and now we've written over their seeked offset.

Maybe instead we should reset the fetched position to the consumed position?

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.

@hachikuji I thought about this, but consumed() may return null for the first time so we cannot rely on that value either. Maybe we should just combine these two? I.e.:

If consumed() != null, set to consumed;
otherwise this MUST be the first fetch ever returned before any seek() was called, hence resetting to first offset should be safe.


continue;
}

Expand Down Expand Up @@ -445,8 +452,10 @@ private void handleFetchResponse(ClientResponse resp, FetchRequest request) {
for (Map.Entry<TopicPartition, FetchResponse.PartitionData> entry : response.responseData().entrySet()) {
TopicPartition tp = entry.getKey();
FetchResponse.PartitionData partition = entry.getValue();
if (!subscriptions.assignedPartitions().contains(tp)) {
log.debug("Ignoring fetched data for partition {} which is no longer assigned.", tp);
if (!subscriptions.isFetchable(tp)) {
// this can happen when a rebalance happened or a partition consumption paused
// while fetch is still in-flight
log.debug("Ignoring fetched records for partition {} since it is no longer fetchable", tp);
} else if (partition.errorCode == Errors.NONE.code()) {
long fetchOffset = request.fetchData().get(tp).offset;

Expand Down