-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
[Issue 9438][pulsar-client] Fix inconsistent equals and hashCode for MessageIds #9440
Conversation
pulsar-client/src/main/java/org/apache/pulsar/client/impl/MessageIdImpl.java
Outdated
Show resolved
Hide resolved
57b7ddb
to
5395426
Compare
I also noticed the |
@merlimat Can you review it again? |
pulsar-client/src/main/java/org/apache/pulsar/client/impl/MessageIdImpl.java
Outdated
Show resolved
Hide resolved
pulsar-client/src/main/java/org/apache/pulsar/client/impl/BatchMessageIdImpl.java
Show resolved
Hide resolved
@codelipenghui @315157973 responded to your comments. I get that the implementation for this is a little weird, so let me know if you have any other suggestions to achieve the same goal. Ideally we would have single message ID type that can represent either batched or unbatched messages, but I'm not sure how feasible that is without breaking changes. |
Thinking out loud: What about keeping your new tests cases, they express exactly the problem. in order to implement hashCode you could add a static utility method that receives all of the relevant fields:
the same can be done for the equals method
|
@eolivelli That sounds workable. I'd assume we'd want to do the same for |
Sure |
I don’t know much about the historical reasons, why is there such a parameter as There is a special treatment for NO_BATCH in equals. When batchIndex=-1 (NO_BATCH), only ledgerId, entryId and partitionIndex need to be equal. Can the HashCode also be specially processed? When batchIndex=-1, batchIndex is not allowed to participate in the calculation of hashcode |
The constraint is that if two objects are 'equals' to each other they have the same hash code. |
If we do special processing in The problem now is that special processing is done in equals, but not in hashcode: pulsar/pulsar-client/src/main/java/org/apache/pulsar/client/impl/BatchMessageIdImpl.java Line 109 in 6089292
|
@315157973 I'm also unsure about why we have |
The current hashcode is like this If it is consistent with the logic of equal, it should be:
cc @eolivelli |
@315157973 works for me. |
@315157973 Let me clarify what I'm asking. As you mentioned, the current pulsar/pulsar-client/src/main/java/org/apache/pulsar/client/impl/BatchMessageIdImpl.java Line 109 in 6089292
batchIndex it is assumed to be NO_BATCH (-1 ).
And return (int) (31 * (ledgerId + 31 * entryId) + (31 * (long) partitionIndex) + batchIndex); So for The inconsistency is that return (int) (31 * (ledgerId + 31 * entryId) + partitionIndex); This can be fixed by using the the same implementation as in I think you are suggesting changing if(batchIndex == NO_BATCH){
return (int) (31 * (ledgerId + 31 * entryId) + (31 * (long) partitionIndex));
}
return (int) (31 * (ledgerId + 31 * entryId) + (31 * (long) partitionIndex) + batchIndex); Which would only be necessary if Or are you suggesting only treating |
5395426
to
92db163
Compare
I talked to @sijie and he said that |
92db163
to
cb72764
Compare
@315157973 @eolivelli I updated to delegate to the static method. I think I understand what you're saying now. Your change to |
b43cf81
to
f946510
Compare
f946510
to
c77db43
Compare
works for me |
Thanks @315157973. I added some tests for some of the edge cases, but I'd appreciate feedback on any other tests I can add. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -73,7 +73,7 @@ public void testGreaterThan() { | |||
assertTrue(batchMessageId2.compareTo(batchMessageId3) > 0, "Expected to be greater than"); | |||
assertTrue(batchMessageId2.compareTo(batchMessageId4) > 0, "Expected to be greater than"); | |||
assertTrue(batchMessageId2.compareTo(batchMessageId5) > 0, "Expected to be greater than"); | |||
assertTrue(batchMessageId3.compareTo(batchMessageId4) > 0, "Expected to be greater than"); | |||
assertTrue(batchMessageId4.compareTo(batchMessageId3) > 0, "Expected to be greater than"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting catch
@merlimat can you take a final look ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job!
@merlimat Could you please help review it again |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job! LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
This patch is too dangerous for 2.7.2 IMHO, I have removed the release/2.7.2 label |
Fixes #9438
Motivation
Since
MessageId
is an opaque interface that has several subclasses, in general those subclasses should try to behave the same way with respect to one another if they refer to the same message. They should also follow the standard contract for Javaequals
andhashCode
methods.Modifications
Provided a single
equals
andhashCode
implementation forMessageIdImpl
that takes into account the batch version as well. ChangedTopicMessageIdImpl
to not take into account the topic anymore.Verifying this change
BatchMessageIdImpl
TopicMessageIdImpl