Skip to content

fix(broker): non-blocking inbox send prevents heartbeat timeout under load - #22

Merged
jamesainslie merged 2 commits into
mainfrom
fix-consumer-stall
Mar 30, 2026
Merged

jamesainslie merged 2 commits into
mainfrom
fix-consumer-stall

Conversation

@jamesainslie

Copy link
Copy Markdown
Collaborator

Summary

Fixed a critical bug where publishers disconnected during sustained high-throughput publishing (~700K+ messages).

Root cause: Queue.Publish blocked on a full inbox channel (capacity 4096) while called from the connection's read loop. This stalled heartbeat frame processing, causing the heartbeat timeout goroutine to close the connection.

Fix: Non-blocking send on the inbox channel. If full, falls back to synchronous PublishSync (writes directly to the store under lock). This provides backpressure without blocking the read loop.

Verified on 32-core AMD EPYC-Milan (251GB RAM)

Scenario Before fix After fix
1P/1C, 500K msgs Stalls at ~560K, 0 consumed 30,903 msg/s, all consumed
4P/4C, 1M msgs 0 consumed 85,586 msg/s, all consumed

Test plan

  • 574 tests passing with -race
  • All guarantee tests pass
  • 1M messages over TCP with no stalls (verified locally and on server)
  • golangci-lint clean

…meout

Queue.Publish previously blocked on a full inbox channel (capacity 4096).
When called from the connection read loop during sustained high-throughput
publishing, this blocked the read loop goroutine, preventing heartbeat
frame processing. The heartbeat timeout goroutine would then close the
connection, causing publisher disconnects at ~700K messages.

Fix: use a non-blocking send on the inbox channel. If the inbox is full,
fall back to synchronous PublishSync (write directly to the store under
lock). This provides backpressure without stalling the read loop.

Verified: 1M messages at 85K msg/s (4P/4C) on 32-core AMD EPYC with
no publisher disconnects or consumer stalls.
@jamesainslie
jamesainslie merged commit 2428c58 into main Mar 30, 2026
2 checks passed
@jamesainslie
jamesainslie deleted the fix-consumer-stall branch March 30, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant