Skip to content

Commit 3a30432

Browse files
authored
fix: intersect BitList tail invokers in state routing (#16395)
1 parent eb1d8ab commit 3a30432

3 files changed

Lines changed: 64 additions & 8 deletions

File tree

dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/BitList.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,26 @@ public synchronized E getByIndex(int index) {
114114
}
115115

116116
/**
117-
* And operation between two bitList. Return a new cloned list.
118-
* TailList in source bitList will be totally saved even if it is not appeared in the target bitList.
117+
* And operation between two bitList.
119118
*
120119
* @param target target bitList
121-
* @return this bitList only contains those elements contain in both two list and source bitList's tailList
120+
* @return this bitList only contains elements contained in both lists
122121
*/
123122
public synchronized BitList<E> and(BitList<E> target) {
124-
rootSet.and(target.rootSet);
125-
if (target.getTailList() != null) {
126-
target.getTailList().forEach(this::addToTailList);
123+
if (originList == target.originList) {
124+
rootSet.and(target.rootSet);
125+
} else {
126+
BitSet resultSet = new BitSet();
127+
for (int bitIndex = rootSet.nextSetBit(0); bitIndex >= 0; bitIndex = rootSet.nextSetBit(bitIndex + 1)) {
128+
if (target.contains(originList.get(bitIndex))) {
129+
resultSet.set(bitIndex);
130+
}
131+
}
132+
rootSet.clear();
133+
rootSet.or(resultSet);
134+
}
135+
if (CollectionUtils.isNotEmpty(tailList)) {
136+
tailList.removeIf(e -> !target.contains(e));
127137
}
128138
return this;
129139
}

dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionStateRouterTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,33 @@ void testRoute_matchFilter() {
196196
Assertions.assertEquals(1, filteredInvokers6.size());
197197
}
198198

199+
@Test
200+
void testRoute_shouldFilterTailInvokers() {
201+
List<Invoker<String>> originInvokers = new ArrayList<Invoker<String>>();
202+
Invoker<String> targetInvoker =
203+
new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
204+
Invoker<String> tailInvoker =
205+
new MockInvoker<String>(URL.valueOf("dubbo://10.20.3.4:20880/com.foo.BarService"));
206+
originInvokers.add(targetInvoker);
207+
BitList<Invoker<String>> invokers = new BitList<>(originInvokers);
208+
invokers.add(tailInvoker);
209+
210+
StateRouter<String> router = new ConditionStateRouterFactory()
211+
.getRouter(
212+
String.class, getRouteUrl("=> host = 10.20.3.3").addParameter(FORCE_KEY, String.valueOf(true)));
213+
214+
BitList<Invoker<String>> filteredInvokers = router.route(
215+
invokers,
216+
URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"),
217+
new RpcInvocation(),
218+
false,
219+
new Holder<>());
220+
221+
Assertions.assertEquals(1, filteredInvokers.size());
222+
Assertions.assertTrue(filteredInvokers.contains(targetInvoker));
223+
Assertions.assertFalse(filteredInvokers.contains(tailInvoker));
224+
}
225+
199226
@Test
200227
void testRoute_methodRoute() {
201228
Invocation invocation = new RpcInvocation("getFoo", "com.foo.BarService", "", new Class<?>[0], new Object[0]);

dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/state/BitListTest.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,29 @@ void testIntersect() {
9696

9797
aBitList.add("D");
9898
intersectBitList = aBitList.and(bBitList);
99-
Assertions.assertEquals(3, intersectBitList.size());
99+
Assertions.assertEquals(2, intersectBitList.size());
100100
Assertions.assertEquals(totalList.get(0), intersectBitList.get(0));
101101
Assertions.assertEquals(totalList.get(1), intersectBitList.get(1));
102-
Assertions.assertEquals("D", intersectBitList.get(2));
102+
Assertions.assertFalse(intersectBitList.contains("D"));
103+
}
104+
105+
@Test
106+
void testIntersectTailList() {
107+
List<String> list = Arrays.asList("A", "B");
108+
BitList<String> bitList = new BitList<>(list);
109+
bitList.add("C");
110+
bitList.add("D");
111+
112+
BitList<String> target = new BitList<>(list);
113+
target.remove("B");
114+
target.add("D");
115+
116+
BitList<String> intersectBitList = bitList.and(target);
117+
Assertions.assertEquals(2, intersectBitList.size());
118+
Assertions.assertEquals("A", intersectBitList.get(0));
119+
Assertions.assertEquals("D", intersectBitList.get(1));
120+
Assertions.assertFalse(intersectBitList.contains("B"));
121+
Assertions.assertFalse(intersectBitList.contains("C"));
103122
}
104123

105124
@Test

0 commit comments

Comments
 (0)