Skip to content

Commit b902bfa

Browse files
authored
fix(pooling): make active-connection assertions race-free (#103)
* fix(pooling): make active-connection assertions race-free box.stat.net().CONNECTIONS.current is updated asynchronously by the IProto worker, so reading it once right after starting clients can return a stale value and flake ConnectionPoolReconnectsTest. Replace the single read in BasePoolTest#getActiveConnectionsCount with a bounded Lua poll that waits until the counter stops changing, and add waitForActiveConnections helper for tests that need to assert a specific count.
1 parent 276603b commit b902bfa

3 files changed

Lines changed: 40 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,21 @@
66

77
- Add `tarantool-spring-data-40` module with support for Spring Boot 4.0.x and Spring Data 4.0.x
88

9+
### Bug fixes
10+
11+
- Fix flaky `ConnectionPoolReconnectsTest` assertions on active connection count by polling
12+
`box.stat.net().CONNECTIONS.current` from Lua until it holds the same value across
13+
5 consecutive reads at 100ms intervals, instead of a single read that races with the IProto worker
14+
915
### Testcontainers
1016

1117
- Add TQE 3.x (message-queue-ee 3.x) integration on top of the
1218
existing TQE 2.x support; consolidate the TQE 2.x / 3.x test
1319
surface into a single parameterized suite.
14-
- Add constructor/builder parameters to supply the initial Lua script as a string or as a file path, and optional additional script paths copied into the container data directory (`Tarantool2Container`, `CartridgeClusterContainer`, `VshardClusterContainer`); simplify bundled `server.lua` accordingly.
20+
- Add constructor/builder parameters to supply the initial Lua script as a string or as a file path,
21+
and optional additional script paths copied into the container data directory
22+
(`Tarantool2Container`, `CartridgeClusterContainer`, `VshardClusterContainer`);
23+
simplify bundled `server.lua` accordingly.
1524
- Upgrade TQE to v3.5.0.
1625
- Extract `ObjectMapper` to a static field in the test `tdg.Utils` helper to avoid recreating it on every `sendUsers`/`getUsers` call.
1726

@@ -21,8 +30,10 @@
2130

2231
### Documentation
2332

24-
- Document supported Java types for Tarantool data mapping in `tuple_pojo_mapping` docs (RU/EN), including Tarantool extension types (`decimal`, `uuid`, `datetime`, `interval`, `tuple`) and related mapping notes.
25-
- Document Jackson MsgPack deserialization: integers, `bin`/`str` vs `byte[]`/`String`, floating-point vs `decimal`; reference `jackson-dataformat-msgpack` for defaults and type coercion.
33+
- Document supported Java types for Tarantool data mapping in `tuple_pojo_mapping` docs (RU/EN),
34+
including Tarantool extension types (`decimal`, `uuid`, `datetime`, `interval`, `tuple`) and related mapping notes.
35+
- Document Jackson MsgPack deserialization: integers, `bin`/`str` vs `byte[]`/`String`, floating-point vs `decimal`;
36+
reference `jackson-dataformat-msgpack` for defaults and type coercion.
2637

2738
### Dependencies
2839
- Updated dependencies:

tarantool-pooling/src/test/java/io/tarantool/pool/integration/BasePoolTest.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.concurrent.CompletionException;
1616
import java.util.concurrent.ThreadLocalRandom;
1717

18+
import static org.junit.jupiter.api.Assertions.assertEquals;
1819
import static org.junit.jupiter.api.Assertions.assertTrue;
1920
import static org.junit.jupiter.api.Assertions.fail;
2021
import io.micrometer.core.instrument.Counter;
@@ -93,10 +94,25 @@ protected void execLua(TarantoolContainer<?> container, String command) {
9394

9495
protected int getActiveConnectionsCount(TarantoolContainer<?> tt) {
9596
try {
96-
List<? extends Object> result =
97-
TarantoolContainerClientHelper.executeCommandDecoded(
98-
tt, "return box.stat.net().CONNECTIONS.current");
99-
return (Integer) result.get(0) - 1;
97+
// IProto worker updates CONNECTIONS.current asynchronously; require 5 consecutive equal
98+
// reads at 100ms intervals before trusting the value (100 iters = 10s safety net).
99+
String lua =
100+
"local last = box.stat.net().CONNECTIONS.current;"
101+
+ " local stable = 1;"
102+
+ " for i = 1, 100 do"
103+
+ " require('fiber').sleep(0.1);"
104+
+ " local cur = box.stat.net().CONNECTIONS.current;"
105+
+ " if cur == last then"
106+
+ " stable = stable + 1;"
107+
+ " if stable >= 5 then return cur - 1 end;"
108+
+ " else"
109+
+ " last = cur;"
110+
+ " stable = 1;"
111+
+ " end;"
112+
+ " end;"
113+
+ " return last - 1";
114+
List<? extends Object> result = TarantoolContainerClientHelper.executeCommandDecoded(tt, lua);
115+
return (Integer) result.get(0);
100116
} catch (Exception e) {
101117
throw new RuntimeException(e);
102118
}
@@ -106,6 +122,10 @@ protected int getActiveConnectionsCountDelta(TarantoolContainer<?> tt, int basel
106122
return getActiveConnectionsCount(tt) - baseline;
107123
}
108124

125+
protected void waitForActiveConnections(TarantoolContainer<?> tt, int expected) {
126+
assertEquals(expected, getActiveConnectionsCount(tt));
127+
}
128+
109129
protected MeterRegistry createMetricsRegistry() {
110130
MeterRegistry metricsRegistry = new SimpleMeterRegistry();
111131
LongTaskTimer.builder("request.timer")

tarantool-pooling/src/test/java/io/tarantool/pool/integration/ConnectionPoolReconnectsTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public void testReconnectAfterNodeFailure() throws Exception {
7777
assertTrue(pool.hasAvailableClients());
7878
List<IProtoClient> clients = getConnects(pool, "node-a", count1);
7979
assertTrue(pingClients(clients));
80-
assertEquals(count1, getActiveConnectionsCount(tt));
80+
waitForActiveConnections(tt, count1);
8181

8282
tt.stop();
8383
Thread.sleep(1000);
@@ -110,7 +110,7 @@ public void testReconnectAfterNodeFailure() throws Exception {
110110
});
111111

112112
assertTrue(pingClients(clients));
113-
assertEquals(count1, getActiveConnectionsCount(tt));
113+
waitForActiveConnections(tt, count1);
114114

115115
assertEquals(count1, metricsRegistry.get("pool.size").gauge().value());
116116
assertEquals(count1, metricsRegistry.get("pool.available").gauge().value());

0 commit comments

Comments
 (0)