You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(qwp): split role-reject observability out of onDurableAckUnavailable (M10)
Unreleased commits d0a794a/4200697 made onDurableAckUnavailable fire for
BOTH the durable-ack capability gap and the transient all-replica window,
passing whichever mode-local counter was current with no discriminator. A
listener written against the released 1.3.4 contract (capability-gap-only,
counter marching toward the 16-attempt escalation) saw a non-monotonic,
ambiguous stream: alerting keyed on "attemptNumber approaching 16"
false-positived on role-reject windows (which never escalate, Invariant B)
and could miss real budget pressure.
Split the streams before 1.3.5 ships the break:
- new default method onPrimaryUnavailable(slotPath, attemptNumber) carries
the role-reject count (retried indefinitely, never escalates); the no-op
default keeps 1.3.4 implementors source/binary compatible
- onDurableAckUnavailable reverts to the released capability-gap-only
semantics; its episode counter still restarts on an intervening role
reject (topology churn grants a fresh settle budget), but the reset is
now attributable to the onPrimaryUnavailable delivery between episodes
- budget/episode/escalation logic untouched (Invariant B tests unmodified
except for the per-stream assertion split)
Copy file name to clipboardExpand all lines: core/src/test/java/io/questdb/client/test/cutlass/qwp/client/sf/cursor/BackgroundDrainerDurableAckRetryTest.java
+76-8Lines changed: 76 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -44,6 +44,7 @@
44
44
45
45
importjava.nio.file.Paths;
46
46
importjava.util.ArrayList;
47
+
importjava.util.Arrays;
47
48
importjava.util.Collections;
48
49
importjava.util.List;
49
50
importjava.util.concurrent.CountDownLatch;
@@ -562,14 +563,19 @@ public void testRoleRejectChurnDoesNotConsumeCapabilityGapBudgetInvariantB() thr
562
563
cap, listener.lastPersistentTotalAttempts.get());
563
564
assertEquals("full settle budget must be granted after the transient window",
564
565
roleRejects + cap, factory.attempts());
565
-
// Per-mode attempt numbering: 1..20 for the transient window, then a
566
-
// fresh 1..15 for the gap episode (the 16th fires persistent-failure).
567
-
assertEquals(roleRejects + cap - 1, listener.unavailableAttempts.size());
566
+
// M10 split: the transient all-replica window lands on the
567
+
// onPrimaryUnavailable stream (1..20), the capability-gap episode
568
+
// on onDurableAckUnavailable (1..15; the 16th fires
569
+
// persistent-failure instead). Neither stream sees the other's
570
+
// counter, so a listener alerting on "attemptNumber approaching
571
+
// the cap" no longer false-positives on role-reject churn.
0 commit comments