Skip to content

Commit 05701d7

Browse files
labuladongnodece
authored andcommitted
[fix][test] flaky test testCanRecoverConsumptionWhenLiftMaxUnAckedMessagesRestriction (#18726)
(cherry picked from commit 2d205c9)
1 parent f38ea11 commit 05701d7

File tree

1 file changed

+56
-80
lines changed

1 file changed

+56
-80
lines changed

pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeySharedSubscriptionTest.java

+56-80
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,35 @@
1818
*/
1919
package org.apache.pulsar.client.impl;
2020

21-
import com.google.common.collect.Maps;
2221
import com.google.common.collect.Sets;
23-
import lombok.Cleanup;
22+
import java.nio.charset.StandardCharsets;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import java.util.Map;
26+
import java.util.Set;
27+
import java.util.UUID;
28+
import java.util.concurrent.ConcurrentHashMap;
29+
import java.util.concurrent.TimeUnit;
30+
import java.util.concurrent.atomic.AtomicBoolean;
31+
import java.util.concurrent.atomic.AtomicLong;
2432
import org.apache.commons.lang3.RandomStringUtils;
33+
import org.apache.pulsar.client.api.BatcherBuilder;
2534
import org.apache.pulsar.client.api.Consumer;
35+
import org.apache.pulsar.client.api.ConsumerBuilder;
36+
import org.apache.pulsar.client.api.KeySharedPolicy;
2637
import org.apache.pulsar.client.api.MessageId;
2738
import org.apache.pulsar.client.api.Producer;
2839
import org.apache.pulsar.client.api.ProducerConsumerBase;
29-
import org.apache.pulsar.client.api.PulsarClient;
3040
import org.apache.pulsar.client.api.PulsarClientException;
41+
import org.apache.pulsar.client.api.Range;
3142
import org.apache.pulsar.client.api.SubscriptionType;
43+
import org.apache.pulsar.common.util.Murmur3_32Hash;
3244
import org.awaitility.Awaitility;
3345
import org.testng.Assert;
3446
import org.testng.annotations.AfterMethod;
3547
import org.testng.annotations.BeforeMethod;
3648
import org.testng.annotations.DataProvider;
3749
import org.testng.annotations.Test;
38-
import java.nio.charset.StandardCharsets;
39-
import java.util.ArrayList;
40-
import java.util.List;
41-
import java.util.Map;
42-
import java.util.Set;
43-
import java.util.UUID;
44-
import java.util.concurrent.TimeUnit;
45-
import java.util.concurrent.atomic.AtomicBoolean;
46-
import java.util.concurrent.atomic.AtomicLong;
4750

4851
@Test(groups = "broker-impl")
4952
public class KeySharedSubscriptionTest extends ProducerConsumerBase {
@@ -70,91 +73,58 @@ public Object[][] subType() {
7073
@Test(dataProvider = "subType")
7174
public void testCanRecoverConsumptionWhenLiftMaxUnAckedMessagesRestriction(SubscriptionType subscriptionType)
7275
throws PulsarClientException {
73-
PulsarClient pulsarClient = PulsarClient.builder().
74-
serviceUrl(lookupUrl.toString())
75-
.build();
7676
final int totalMsg = 1000;
7777
String topic = "broker-close-test-" + RandomStringUtils.randomAlphabetic(5);
78-
Map<Consumer<?>, List<MessageId>> nameToId = Maps.newConcurrentMap();
78+
Map<Consumer<?>, List<MessageId>> nameToId = new ConcurrentHashMap<>();
7979
Set<MessageId> pubMessages = Sets.newConcurrentHashSet();
8080
Set<MessageId> recMessages = Sets.newConcurrentHashSet();
8181
AtomicLong lastActiveTime = new AtomicLong();
8282
AtomicBoolean canAcknowledgement = new AtomicBoolean(false);
8383

84-
@Cleanup
85-
Consumer<byte[]> consumer1 = pulsarClient.newConsumer()
86-
.topic(topic)
87-
.subscriptionName("sub-1")
88-
.subscriptionType(subscriptionType)
89-
.consumerName("con-1")
90-
.messageListener((cons1, msg) -> {
91-
lastActiveTime.set(System.currentTimeMillis());
92-
nameToId.computeIfAbsent(cons1,(k) -> new ArrayList<>())
93-
.add(msg.getMessageId());
94-
recMessages.add(msg.getMessageId());
95-
if (canAcknowledgement.get()) {
96-
try {
97-
cons1.acknowledge(msg);
98-
} catch (PulsarClientException e) {
99-
throw new RuntimeException(e);
100-
}
101-
}
102-
})
103-
.subscribe();
104-
@Cleanup
105-
Consumer<byte[]> consumer2 = pulsarClient.newConsumer()
106-
.topic(topic)
107-
.subscriptionName("sub-1")
108-
.subscriptionType(subscriptionType)
109-
.messageListener((cons2, msg) -> {
110-
lastActiveTime.set(System.currentTimeMillis());
111-
nameToId.computeIfAbsent(cons2,(k) -> new ArrayList<>())
112-
.add(msg.getMessageId());
113-
recMessages.add(msg.getMessageId());
114-
if (canAcknowledgement.get()) {
115-
try {
116-
cons2.acknowledge(msg);
117-
} catch (PulsarClientException e) {
118-
throw new RuntimeException(e);
84+
List<Consumer<?>> consumerList = new ArrayList<>();
85+
// create 3 consumers
86+
for (int i = 0; i < 3; i++) {
87+
ConsumerBuilder<byte[]> builder = pulsarClient.newConsumer()
88+
.topic(topic)
89+
.subscriptionName("sub-1")
90+
.subscriptionType(subscriptionType)
91+
.messageListener((consumer, msg) -> {
92+
lastActiveTime.set(System.currentTimeMillis());
93+
nameToId.computeIfAbsent(consumer, (k) -> new ArrayList<>())
94+
.add(msg.getMessageId());
95+
recMessages.add(msg.getMessageId());
96+
if (canAcknowledgement.get()) {
97+
try {
98+
consumer.acknowledge(msg);
99+
} catch (PulsarClientException e) {
100+
throw new RuntimeException(e);
101+
}
119102
}
120-
}
121-
})
122-
.consumerName("con-2")
123-
.subscribe();
124-
@Cleanup
125-
Consumer<byte[]> consumer3 = pulsarClient.newConsumer()
126-
.topic(topic)
127-
.subscriptionName("sub-1")
128-
.subscriptionType(subscriptionType)
129-
.messageListener((cons3, msg) -> {
130-
lastActiveTime.set(System.currentTimeMillis());
131-
nameToId.computeIfAbsent(cons3,(k) -> new ArrayList<>())
132-
.add(msg.getMessageId());
133-
recMessages.add(msg.getMessageId());
134-
if (canAcknowledgement.get()) {
135-
try {
136-
cons3.acknowledge(msg);
137-
} catch (PulsarClientException e) {
138-
throw new RuntimeException(e);
139-
}
140-
}
141-
})
142-
.consumerName("con-3")
143-
.subscribe();
103+
});
104+
105+
if (subscriptionType == SubscriptionType.Key_Shared) {
106+
// ensure every consumer can be distributed messages
107+
int hash = Murmur3_32Hash.getInstance().makeHash(("key-" + i).getBytes())
108+
% KeySharedPolicy.DEFAULT_HASH_RANGE_SIZE;
109+
builder.keySharedPolicy(KeySharedPolicy.stickyHashRange().ranges(Range.of(hash, hash)));
110+
}
111+
112+
consumerList.add(builder.subscribe());
113+
}
144114

145-
@Cleanup
146115
Producer<byte[]> producer = pulsarClient.newProducer()
147116
.topic(topic)
148117
.enableBatching(true)
149118
.batchingMaxPublishDelay(1, TimeUnit.MILLISECONDS)
150119
// We chose 9 because the maximum unacked message is 10
151120
.batchingMaxMessages(9)
121+
.batcherBuilder(BatcherBuilder.KEY_BASED)
152122
.create();
153123

154124
for (int i = 0; i < totalMsg; i++) {
155-
producer.sendAsync(UUID.randomUUID().toString()
156-
.getBytes(StandardCharsets.UTF_8))
157-
.thenAccept(pubMessages::add);
125+
byte[] msg = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8);
126+
producer.newMessage().key("key-" + (i % 3)).value(msg)
127+
.sendAsync().thenAccept(pubMessages::add);
158128
}
159129

160130
// Wait for all consumers can not read more messages. the consumers are stuck by max unacked messages.
@@ -176,7 +146,7 @@ public void testCanRecoverConsumptionWhenLiftMaxUnAckedMessagesRestriction(Subsc
176146

177147
// Wait for all consumers to continue receiving messages.
178148
Awaitility.await()
179-
.atMost(30, TimeUnit.SECONDS)
149+
.atMost(15, TimeUnit.SECONDS)
180150
.pollDelay(5, TimeUnit.SECONDS)
181151
.until(() ->
182152
(System.currentTimeMillis() - lastActiveTime.get()) > TimeUnit.SECONDS.toMillis(5));
@@ -186,5 +156,11 @@ public void testCanRecoverConsumptionWhenLiftMaxUnAckedMessagesRestriction(Subsc
186156
Assert.assertEquals(pubMessages.size(), totalMsg);
187157
Assert.assertEquals(pubMessages.size(), recMessages.size());
188158
Assert.assertTrue(recMessages.containsAll(pubMessages));
159+
160+
// cleanup
161+
producer.close();
162+
for (Consumer<?> consumer : consumerList) {
163+
consumer.close();
164+
}
189165
}
190166
}

0 commit comments

Comments
 (0)