-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
[fix][broker] Key-shared subscription must follow consumer redelivery as per shared sub semantic #21657
base: master
Are you sure you want to change the base?
[fix][broker] Key-shared subscription must follow consumer redelivery as per shared sub semantic #21657
Changes from 1 commit
41d2c60
a012718
9a44010
eb86950
f419701
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -602,7 +602,7 @@ | |
|
||
for (int i = 0; i < 20; i++) { | ||
Message<Integer> msg = c2.receive(); | ||
assertEquals(msg.getValue().intValue(), i); | ||
|
||
c2.acknowledge(msg); | ||
} | ||
|
@@ -706,7 +706,7 @@ | |
} | ||
|
||
// C2 will not be able to receive any messages until C1 is done processing whatever he got prefetched | ||
assertNull(c2.receive(100, TimeUnit.MILLISECONDS)); | ||
Check failure on line 709 in pulsar-broker/src/test/java/org/apache/pulsar/client/api/KeySharedSubscriptionTest.java GitHub Actions / Flaky tests suiteKeySharedSubscriptionTest.testRemoveFirstConsumer
|
||
|
||
c1.close(); | ||
|
||
|
@@ -881,7 +881,7 @@ | |
received = consumer2.receive(1, TimeUnit.SECONDS); | ||
} catch (PulsarClientException ignore) { | ||
} | ||
Assert.assertNull(received); | ||
Check failure on line 884 in pulsar-broker/src/test/java/org/apache/pulsar/client/api/KeySharedSubscriptionTest.java GitHub Actions / Flaky tests suiteKeySharedSubscriptionTest.testContinueDispatchMessagesWhenMessageTTL
|
||
|
||
@Cleanup | ||
Consumer<Integer> consumer3 = pulsarClient.newConsumer(Schema.INT32) | ||
|
@@ -1630,4 +1630,63 @@ | |
log.info("Got {} other messages...", sum); | ||
Assert.assertEquals(sum, delayedMessages + messages); | ||
} | ||
|
||
@Test | ||
public void test() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we add a more meaningful test ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops.. sorry, I just added this test to create an issue. let me fix tests and naming. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done. |
||
throws Exception { | ||
String topic = "persistent://public/default/key_shared-" + UUID.randomUUID(); | ||
boolean enableBatch = false; | ||
Set<Integer> values = new HashSet<>(); | ||
|
||
@Cleanup | ||
Consumer<Integer> consumer1 = createConsumer(topic); | ||
|
||
@Cleanup | ||
Producer<Integer> producer = createProducer(topic, enableBatch); | ||
int count = 0; | ||
for (int i = 0; i < 10; i++) { | ||
// Send the same key twice so that we'll have a batch message | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see that enableBatch is false, did you want to also add that case ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed those comments. |
||
String key = String.valueOf(random.nextInt(NUMBER_OF_KEYS)); | ||
producer.newMessage().key(key).value(count++).send(); | ||
} | ||
|
||
@Cleanup | ||
Consumer<Integer> consumer2 = createConsumer(topic); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consumer2 will be closed by lombok after last usage. The point in time you close the consumer may alter the execution of the test There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consumer2 needs to be open for the test to consume all messages and then let it be cleaned by Lombok, we don't have to close it explicitly and it won't impact the test as well. |
||
|
||
for (int i = 0; i < 10; i++) { | ||
// Send the same key twice so that we'll have a batch message | ||
String key = String.valueOf(random.nextInt(NUMBER_OF_KEYS)); | ||
producer.newMessage().key(key).value(count++).send(); | ||
} | ||
|
||
@Cleanup | ||
Consumer<Integer> consumer3 = createConsumer(topic); | ||
|
||
consumer2.redeliverUnacknowledgedMessages(); | ||
|
||
for (int i = 0; i < 10; i++) { | ||
// Send the same key twice so that we'll have a batch message | ||
String key = String.valueOf(random.nextInt(NUMBER_OF_KEYS)); | ||
producer.newMessage().key(key).value(count++).send(); | ||
} | ||
consumer1.close(); | ||
|
||
for(int i = 0; i < count; i++) { | ||
Message<Integer> msg = consumer2.receive(100, TimeUnit.MILLISECONDS); | ||
if (msg!=null) { | ||
values.add(msg.getValue()); | ||
} else { | ||
break; | ||
} | ||
} | ||
for(int i = 0; i < count; i++) { | ||
Message<Integer> msg = consumer3.receive(1, TimeUnit.MILLISECONDS); | ||
if (msg!=null) { | ||
values.add(msg.getValue()); | ||
} else { | ||
break; | ||
} | ||
} | ||
Comment on lines
+1676
to
+1691
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this test is currently invalid. Messages would need to be acknowledged and consumed concurrently. This test passes at least in branch-3.3 when making the changes. |
||
assertEquals(values.size(), count); | ||
} | ||
} |
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.
These codes guarantee the ordering of messages during the scenario below:
k1,k2
,recent-join: null
k3,k4
,recent-join: null
M1(k1), M2(k2)
1000
messages (M3(k3)...M1002(k3)
)k2
which from Consumer 1k1
k3,k4
k2
,recent-join: M1002
k3
which from Consumer 2k4
which from Consumer 2k1,k3
,recent-join: null
k2, k4
,recent-join: M1002
M3(k3)...M1000(k3)
, the incoming queue is full now.k3
which from Consumer 1k1
,recent-join: null
k2, k4
,recent-join: M1002
k3
,recent-join: M1002
M1001(k3)...M1002(k3)
I think we should solve the issue above first, then try to improve here.
Related to #20776, please take a 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.
@poorbarcode can you share the URL where we have defined the contract of key-shared sub.
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.
I do not know what URL you wanted, is the doc of Key_Share Subscription Doc?
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.
@poorbarcode I mean do we have any document where we have shared what kind of ordering guarantee we provide to users? because as I said in the issue, once one consumer is closed, broker can redeliver unack messages of that consumers without considering the ordering instead blocking forever.
So, I just want to see if we have any doc where we have defined what user can expect in terms ordering for key-shared sub. I had checked earlier URL which you shared but that doesn't talk about the ordering or redelivery ordering.
In this PR with latest commit, It maintains the ordering guarantee but it also handles redelivery of unack messages of closed consumer without blocking dispatcher forever.
So, if we have any contract defined then we can check if this PR violates the user contract for the key-shared subscription because right now, key-shared sub is not usable and it is wasting lot of broker/bookie resources.
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.
Preserving order of processing
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.
thanks @Technoboy- for sharing the link and I was searching for this documentation where it talks about message ordering guarantee for key-shared.
As we have documented new consumer won't receive any messages until the stuck consumer resumes or gets disconnected. So, it must receive if other consumer gets disconnected.
However, right now, dispatching gets stuck when consumer gets disconnected and this PR has the test to reproduce it.
and this PR exactly fixes that issue to unblock dispatching if consumer disconnects and redeliver that consumer's unack messages.
So, this PR should fix that fundamental issue to unblock stuck consumers when they should not be stuck.
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.
Great points @rdhabalia . We can continue to resolve this issue as part of PIP-379, #23309 is the PIP document.
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.
@lhotari you have updated a contract similar to this PR and tried the same behavior in #23309 . then why this PR was blocked for 5 months and then you closed it?
I really don't have words to mention what's going on. does it really look good to people who blocked the PR and came up with a similar approach and did not let other people's work move forward? You also know that the same things keep happening again and again in other PRs as well and you have also witnessed this kind of thing in Pulsar very recently.
@lhotari I don't want to target anyone here but want to ask a simple question: does it look good to do such kind of actions? does it make any difference to their lives by doing it? Because I really don't understand what's going on in this Project recently.