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): SF drainer must never give up on a wall-clock reconnect budget
Invariant B: once rows are in on-disk store-and-forward, the background
drainer must NEVER terminate on reconnect_max_duration_millis. A replica-only
/ all-endpoints-replica window is transient (a replica gets promoted, a
primary reappears), so the client must keep retrying -- with capped backoff --
until a primary is reachable. The ONLY producer-observable terminal condition
is SF exhaustion; the client must never fail because of the drainer.
CursorWebSocketSendLoop.connectLoop (used by both the async-initial-connect
and mid-stream reconnect paths on the I/O thread) enforced the budget as a
give-up deadline: on expiry it recordFatal'd a PROTOCOL_VIOLATION
"...-budget-exhausted" that the next producer call surfaced -> a long-but-
recoverable failover window became a permanent, producer-visible terminal.
Fix: the loop now runs `while (running)` with capped exponential backoff and
returns quietly only when the sender is closing. Genuine terminals (auth /
non-421 upgrade / durable-ack capability gap) still return immediately.
reconnect_max_duration_millis is no longer consulted here; it continues to
bound ONLY the blocking (non-lazy) initial connect in
QwpWebSocketSender.buildAndConnect (connectWithRetry), preserving fail-loud
startup semantics.
Turns green the red-first guards added in questdb-enterprise:
ReplicationTest.testQwpDurableAckDrainerNeverGivesUpPastBudget and the e2e
test_durable_ack_drainer_never_gives_up_on_reconnect_budget.
0 commit comments