Skip to content

[fix][client] Fix unable to send cumulative acknowledgment for last messageId of a batch when enable batch index acknowledgment - #18531

Closed
coderzc wants to merge 1 commit into
apache:masterfrom
coderzc:fix_cumulative_ack
Closed

[fix][client] Fix unable to send cumulative acknowledgment for last messageId of a batch when enable batch index acknowledgment#18531
coderzc wants to merge 1 commit into
apache:masterfrom
coderzc:fix_cumulative_ack

Conversation

@coderzc

@coderzc coderzc commented Nov 18, 2022

Copy link
Copy Markdown
Member

Motivation

When enable batch index acknowledgment, we are unable to send a cumulative acknowledgment for the last messageId of a batch, the root cause is the last messageId of a batch doesn't carry with batch index but due to the wrong comparison in org.apache.pulsar.client.impl.LastCumulativeAck#update make the last messageId can't be sent.

if (batchMessageId == null || batchMessageId.ackCumulative()) {
return doCumulativeAck(msgId, properties, null);

public synchronized void update(final MessageIdImpl messageId, final BitSetRecyclable bitSetRecyclable) {
if (messageId.compareTo(this.messageId) > 0) {
if (this.bitSetRecyclable != null && this.bitSetRecyclable != bitSetRecyclable) {
this.bitSetRecyclable.recycle();
}
set(messageId, bitSetRecyclable);
flushRequired = true;
}
}

    public synchronized void update(final MessageIdImpl messageId, final BitSetRecyclable bitSetRecyclable) {
        if (messageId.compareTo(this.messageId) > 0) {
        // messageId(3,0,-1) < this.messageId(3,0,-1,8) so the following logic cannot be executed
            if (this.bitSetRecyclable != null && this.bitSetRecyclable != bitSetRecyclable) {
                this.bitSetRecyclable.recycle();
            }
            set(messageId, bitSetRecyclable);
            flushRequired = true;
        }
    }

public int compareTo(MessageId o) {
if (o instanceof MessageIdImpl) {
MessageIdImpl other = (MessageIdImpl) o;
int batchIndex = (o instanceof BatchMessageIdImpl) ? ((BatchMessageIdImpl) o).batchIndex : NO_BATCH;
return messageIdCompare(
this.ledgerId, this.entryId, this.partitionIndex, this.batchIndex,
other.ledgerId, other.entryId, other.partitionIndex, batchIndex
);
} else if (o instanceof TopicMessageIdImpl) {
return compareTo(((TopicMessageIdImpl) o).getInnerMessageId());
} else {
throw new UnsupportedOperationException("Unknown MessageId type: " + o.getClass().getName());
}
}

Modifications

Fix the wrong comparison in org.apache.pulsar.client.impl.LastCumulativeAck#update, change it to
(x,y,z) >= (x,y,z,w).

I'm not sure whether modifying MessageImpl.compareTo and BatchMessageIdImpl.compareTo can lead to other problems, so just modify org.apache.pulsar.client.impl.LastCumulativeAck#update

Verifying this change

  • Make sure that the change passes the CI checks.

(Please pick either of the following options)

This change is a trivial rework / code cleanup without any test coverage.

testAcknowledgeCumulative

Documentation

  • doc
  • doc-required
  • doc-not-needed
  • doc-complete

Matching PR in forked repository

PR in forked repository: coderzc#32

@github-actions github-actions Bot added the doc-not-needed Your PR changes do not impact docs label Nov 18, 2022
new BatchMessageIdImpl(newMessageId.ledgerId, newMessageId.entryId, newMessageId.partitionIndex,
Integer.MAX_VALUE);
}
if (newMessageId.compareTo(lastMessageId) > 0) {

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! one question : why not modify the compareTo method directly?

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'm not sure whether modifying MessageImpl.compareTo and BatchMessageIdImpl.compareTo can lead to other problems, I don't know why the previous logic of compareTo was like that.

@coderzc coderzc self-assigned this Nov 20, 2022
@coderzc coderzc added this to the 2.12.0 milestone Nov 20, 2022
if (newMessageId instanceof BatchMessageIdImpl && !(lastMessageId instanceof BatchMessageIdImpl)) {
lastMessageId =
new BatchMessageIdImpl(lastMessageId.ledgerId, lastMessageId.entryId, lastMessageId.partitionIndex,
Integer.MAX_VALUE);

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 logic is already included in #18486

@coderzc coderzc closed this Nov 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

doc-not-needed Your PR changes do not impact docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants