diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe013e5..360fe4fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,21 @@ - Add `tarantool-spring-data-40` module with support for Spring Boot 4.0.x and Spring Data 4.0.x +### Bug fixes + +- Fix flaky `ConnectionPoolReconnectsTest` assertions on active connection count by polling + `box.stat.net().CONNECTIONS.current` from Lua until it holds the same value across + 5 consecutive reads at 100ms intervals, instead of a single read that races with the IProto worker + ### Testcontainers - Add TQE 3.x (message-queue-ee 3.x) integration on top of the existing TQE 2.x support; consolidate the TQE 2.x / 3.x test surface into a single parameterized suite. -- 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. +- 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. - Upgrade TQE to v3.5.0. - Extract `ObjectMapper` to a static field in the test `tdg.Utils` helper to avoid recreating it on every `sendUsers`/`getUsers` call. @@ -21,8 +30,10 @@ ### Documentation -- 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. -- Document Jackson MsgPack deserialization: integers, `bin`/`str` vs `byte[]`/`String`, floating-point vs `decimal`; reference `jackson-dataformat-msgpack` for defaults and type coercion. +- 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. +- Document Jackson MsgPack deserialization: integers, `bin`/`str` vs `byte[]`/`String`, floating-point vs `decimal`; + reference `jackson-dataformat-msgpack` for defaults and type coercion. ### Dependencies - Updated dependencies: diff --git a/tarantool-pooling/src/test/java/io/tarantool/pool/integration/BasePoolTest.java b/tarantool-pooling/src/test/java/io/tarantool/pool/integration/BasePoolTest.java index a3a048b0..7faea613 100644 --- a/tarantool-pooling/src/test/java/io/tarantool/pool/integration/BasePoolTest.java +++ b/tarantool-pooling/src/test/java/io/tarantool/pool/integration/BasePoolTest.java @@ -15,6 +15,7 @@ import java.util.concurrent.CompletionException; import java.util.concurrent.ThreadLocalRandom; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import io.micrometer.core.instrument.Counter; @@ -93,10 +94,25 @@ protected void execLua(TarantoolContainer container, String command) { protected int getActiveConnectionsCount(TarantoolContainer tt) { try { - List result = - TarantoolContainerClientHelper.executeCommandDecoded( - tt, "return box.stat.net().CONNECTIONS.current"); - return (Integer) result.get(0) - 1; + // IProto worker updates CONNECTIONS.current asynchronously; require 5 consecutive equal + // reads at 100ms intervals before trusting the value (100 iters = 10s safety net). + String lua = + "local last = box.stat.net().CONNECTIONS.current;" + + " local stable = 1;" + + " for i = 1, 100 do" + + " require('fiber').sleep(0.1);" + + " local cur = box.stat.net().CONNECTIONS.current;" + + " if cur == last then" + + " stable = stable + 1;" + + " if stable >= 5 then return cur - 1 end;" + + " else" + + " last = cur;" + + " stable = 1;" + + " end;" + + " end;" + + " return last - 1"; + List result = TarantoolContainerClientHelper.executeCommandDecoded(tt, lua); + return (Integer) result.get(0); } catch (Exception e) { throw new RuntimeException(e); } @@ -106,6 +122,10 @@ protected int getActiveConnectionsCountDelta(TarantoolContainer tt, int basel return getActiveConnectionsCount(tt) - baseline; } + protected void waitForActiveConnections(TarantoolContainer tt, int expected) { + assertEquals(expected, getActiveConnectionsCount(tt)); + } + protected MeterRegistry createMetricsRegistry() { MeterRegistry metricsRegistry = new SimpleMeterRegistry(); LongTaskTimer.builder("request.timer") diff --git a/tarantool-pooling/src/test/java/io/tarantool/pool/integration/ConnectionPoolReconnectsTest.java b/tarantool-pooling/src/test/java/io/tarantool/pool/integration/ConnectionPoolReconnectsTest.java index 1050061e..6106a473 100644 --- a/tarantool-pooling/src/test/java/io/tarantool/pool/integration/ConnectionPoolReconnectsTest.java +++ b/tarantool-pooling/src/test/java/io/tarantool/pool/integration/ConnectionPoolReconnectsTest.java @@ -77,7 +77,7 @@ public void testReconnectAfterNodeFailure() throws Exception { assertTrue(pool.hasAvailableClients()); List clients = getConnects(pool, "node-a", count1); assertTrue(pingClients(clients)); - assertEquals(count1, getActiveConnectionsCount(tt)); + waitForActiveConnections(tt, count1); tt.stop(); Thread.sleep(1000); @@ -110,7 +110,7 @@ public void testReconnectAfterNodeFailure() throws Exception { }); assertTrue(pingClients(clients)); - assertEquals(count1, getActiveConnectionsCount(tt)); + waitForActiveConnections(tt, count1); assertEquals(count1, metricsRegistry.get("pool.size").gauge().value()); assertEquals(count1, metricsRegistry.get("pool.available").gauge().value());