Skip to content

Commit 6fd5b61

Browse files
mtopolnikclaude
andcommitted
Drain all buffered ACKs per I/O loop iteration
Previously, tryReceiveAcks() called tryReceiveFrame() exactly once per I/O loop iteration. In the DRAINING state (all batches sent, ACKs still pending), the I/O thread sleeps 10 ms after each call. This meant each in-flight frame added ~10 ms to flush latency: N in-flight frames incurred ~N x 10 ms overhead, even when all ACKs were already sitting in the TCP receive buffer. Fix by looping tryReceiveFrame() until it returns false, draining all buffered ACKs in a single pass. The 10 ms sleep is now reached only when no more data is available, which is the correct condition for avoiding a busy loop. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 999464c commit 6fd5b61

1 file changed

Lines changed: 3 additions & 1 deletion

File tree

core/src/main/java/io/questdb/client/cutlass/qwp/client/WebSocketSendQueue.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,9 @@ private void sendBatch(MicrobatchBuffer batch) {
555555
*/
556556
private void tryReceiveAcks() {
557557
try {
558-
client.tryReceiveFrame(responseHandler);
558+
while (client.tryReceiveFrame(responseHandler)) {
559+
// Drain all buffered ACKs before returning to the I/O loop.
560+
}
559561
} catch (Exception e) {
560562
if (running) {
561563
LOG.error("Error receiving response: {}", e.getMessage());

0 commit comments

Comments
 (0)