From c22759311b9ad77710f9f49378d8e52f42f96914 Mon Sep 17 00:00:00 2001 From: kiryazovi-redis Date: Sat, 18 Jul 2026 19:52:14 +0300 Subject: [PATCH] test(scenario): drive in-flight traffic during MOVING relaxed-timeout check timeoutUnrelaxedOnMovingTest issued a single reactive BLPOP after the MOVING push against an otherwise idle connection. On a re-bind with an empty command stack the client reconnects immediately without relaxing timeouts (relaxation protects in-flight commands; see MaintenanceAwareConnectionWatchdog#rebind), so the measured command saw the normal 30ms timeout and the "at least one relaxed timeout during MOVING" assertion failed. Keep continuous traffic in flight across the maintenance operation so the re-bind is exercised as a real workload would. With traffic in flight the client relaxes during MOVING as designed (verified locally: MOVING command times out at the relaxed 130ms). No client change required. --- .../RelaxedTimeoutConfigurationTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/java/io/lettuce/scenario/RelaxedTimeoutConfigurationTest.java b/src/test/java/io/lettuce/scenario/RelaxedTimeoutConfigurationTest.java index fe89bae60c..eeb7d3827e 100644 --- a/src/test/java/io/lettuce/scenario/RelaxedTimeoutConfigurationTest.java +++ b/src/test/java/io/lettuce/scenario/RelaxedTimeoutConfigurationTest.java @@ -586,6 +586,28 @@ public void timeoutUnrelaxedOnMovingTest() throws InterruptedException { log.info("test timeoutUnrelaxedOnMovingTest started"); TimeoutTestContext context = setupTimeoutTestForMovingUnrelaxed(); + // Keep commands in flight for the duration of the maintenance operation. Timeout + // relaxation protects in-flight commands: on a MOVING/re-bind with an empty command + // stack the client reconnects immediately without relaxing (see + // MaintenanceAwareConnectionWatchdog#rebind), so a test that only issues a single + // reactive command sees the normal timeout. Real workloads have traffic in flight + // across the re-bind; drive continuous traffic so relaxation is exercised as designed. + final AtomicBoolean keepBackgroundTraffic = new AtomicBoolean(true); + Thread backgroundTraffic = new Thread(() -> { + long i = 0; + while (keepBackgroundTraffic.get()) { + try { + context.connection.async().set("moving-inflight-key-" + (i % 50), "v" + i); + i++; + Thread.sleep(1); + } catch (Exception ignored) { + // Errors during the re-bind window are expected; keep the stack busy. + } + } + }, "moving-inflight-traffic"); + backgroundTraffic.setDaemon(true); + backgroundTraffic.start(); + try { log.info("=== MOVING Un-relaxed Timeout Test: Starting maintenance operation ==="); @@ -626,6 +648,8 @@ public void timeoutUnrelaxedOnMovingTest() throws InterruptedException { context.capture.throwIfAssertionFailed(); } finally { + keepBackgroundTraffic.set(false); + backgroundTraffic.join(Duration.ofSeconds(5).toMillis()); context.capture.endTestPhase(); cleanupTimeoutTest(context); }