Skip to content

Commit d12b400

Browse files
committed
Add SAC failover test
References rabbitmq/rabbitmq-server#3753
1 parent 8688fe9 commit d12b400

File tree

1 file changed

+78
-5
lines changed

1 file changed

+78
-5
lines changed

src/test/java/com/rabbitmq/stream/impl/SingleActiveConsumerTest.java

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.concurrent.ConcurrentHashMap;
2727
import java.util.concurrent.CountDownLatch;
2828
import java.util.concurrent.atomic.AtomicInteger;
29+
import java.util.concurrent.atomic.AtomicLong;
2930
import org.junit.jupiter.api.Test;
3031
import org.junit.jupiter.api.extension.ExtendWith;
3132

@@ -36,8 +37,9 @@ public class SingleActiveConsumerTest {
3637
TestUtils.ClientFactory cf;
3738

3839
@Test
39-
void subscribe() throws Exception {
40+
void secondSubscriptionShouldTakeOverAfterFirstOneUnsubscribes() throws Exception {
4041
int messageCount = 10000;
42+
AtomicLong lastReceivedOffset = new AtomicLong(0);
4143
Map<Byte, Boolean> consumerStates = new ConcurrentHashMap<>();
4244
Map<Byte, AtomicInteger> receivedMessages = new ConcurrentHashMap<>();
4345
receivedMessages.put(b(0), new AtomicInteger(0));
@@ -49,21 +51,28 @@ void subscribe() throws Exception {
4951
(client, subscriptionId, offset, msgCount, dataSize) ->
5052
client.credit(subscriptionId, 1))
5153
.messageListener(
52-
(subscriptionId, offset, chunkTimestamp, message) ->
53-
receivedMessages.get(subscriptionId).incrementAndGet())
54+
(subscriptionId, offset, chunkTimestamp, message) -> {
55+
lastReceivedOffset.set(offset);
56+
receivedMessages.get(subscriptionId).incrementAndGet();
57+
})
5458
.consumerUpdateListener(
5559
(client, subscriptionId, active) -> {
5660
consumerStates.put(subscriptionId, active);
5761
consumerUpdateLatch.countDown();
58-
return null;
62+
if (lastReceivedOffset.get() == 0) {
63+
return OffsetSpecification.first();
64+
} else {
65+
return OffsetSpecification.offset(lastReceivedOffset.get() + 1);
66+
}
5967
});
6068
Client client = cf.get(clientParameters);
6169

6270
TestUtils.publishAndWaitForConfirms(cf, messageCount, stream);
6371

72+
String consumerName = "foo";
6473
Map<String, String> parameters = new HashMap<>();
6574
parameters.put("single-active-consumer", "true");
66-
parameters.put("name", "foo");
75+
parameters.put("name", consumerName);
6776
Response response = client.subscribe(b(0), stream, OffsetSpecification.first(), 2, parameters);
6877
assertThat(response.isOk()).isTrue();
6978
response = client.subscribe(b(1), stream, OffsetSpecification.first(), 2, parameters);
@@ -76,5 +85,69 @@ void subscribe() throws Exception {
7685

7786
waitAtMost(
7887
() -> receivedMessages.getOrDefault(b(0), new AtomicInteger(0)).get() == messageCount);
88+
89+
assertThat(lastReceivedOffset).hasPositiveValue();
90+
client.storeOffset(consumerName, stream, lastReceivedOffset.get());
91+
waitAtMost(() -> client.queryOffset(consumerName, stream) == lastReceivedOffset.get());
92+
93+
long firstWaveLimit = lastReceivedOffset.get();
94+
response = client.unsubscribe(b(0));
95+
assertThat(response.isOk()).isTrue();
96+
97+
TestUtils.publishAndWaitForConfirms(cf, messageCount, stream);
98+
99+
waitAtMost(() -> consumerStates.get(b(1)) == true);
100+
101+
waitAtMost(
102+
() -> receivedMessages.getOrDefault(b(1), new AtomicInteger(0)).get() == messageCount);
103+
assertThat(lastReceivedOffset).hasValueGreaterThan(firstWaveLimit);
104+
105+
response = client.unsubscribe(b(1));
106+
assertThat(response.isOk()).isTrue();
107+
}
108+
109+
@Test
110+
void consumerUpdateListenerShouldBeCalledInOrder() throws Exception {
111+
StringBuffer consumerUpdateHistory = new StringBuffer();
112+
Client client =
113+
cf.get(
114+
new ClientParameters()
115+
.consumerUpdateListener(
116+
(client1, subscriptionId, active) -> {
117+
consumerUpdateHistory.append(
118+
String.format("<%d.%b>", subscriptionId, active));
119+
return null;
120+
}));
121+
String consumerName = "foo";
122+
Map<String, String> parameters = new HashMap<>();
123+
parameters.put("single-active-consumer", "true");
124+
parameters.put("name", consumerName);
125+
Response response = client.subscribe(b(0), stream, OffsetSpecification.first(), 2, parameters);
126+
assertThat(response.isOk()).isTrue();
127+
waitAtMost(() -> consumerUpdateHistory.toString().equals("<0.true>"));
128+
for (int i = 1; i < 10; i++) {
129+
byte subscriptionId = b(i);
130+
response =
131+
client.subscribe(subscriptionId, stream, OffsetSpecification.first(), 2, parameters);
132+
assertThat(response.isOk()).isTrue();
133+
waitAtMost(
134+
() ->
135+
consumerUpdateHistory
136+
.toString()
137+
.contains(String.format("<%d.%b>", subscriptionId, false)));
138+
}
139+
140+
for (int i = 0; i < 9; i++) {
141+
byte subscriptionId = b(i);
142+
response = client.unsubscribe(subscriptionId);
143+
assertThat(response.isOk()).isTrue();
144+
waitAtMost(
145+
() ->
146+
consumerUpdateHistory
147+
.toString()
148+
.contains(String.format("<%d.%b>", subscriptionId + 1, true)));
149+
}
150+
response = client.unsubscribe(b(9));
151+
assertThat(response.isOk()).isTrue();
79152
}
80153
}

0 commit comments

Comments
 (0)