Skip to content

fix(consumer): keep read-only queries responsive under backpressure - #430

Open
kacper-li-airspace-intelligence wants to merge 3 commits into
streamnative:masterfrom
kacper-li-airspace-intelligence:fix/consumer-control-backpressure
Open

kacper-li-airspace-intelligence wants to merge 3 commits into
streamnative:masterfrom
kacper-li-airspace-intelligence:fix/consumer-control-backpressure

Conversation

@kacper-li-airspace-intelligence

@kacper-li-airspace-intelligence kacper-li-airspace-intelligence commented Sep 8, 2026 •

Copy link
Copy Markdown

Fetching a schema can hang when the consumer’s receive buffer is full: the engine is waiting to deliver messages, while the application needs the schema before it can resume receiving. Stats, connection checks, and last-message-ID queries have the same problem.

This PR lets those read-only queries use the engine’s current connection directly. A short mutex protects the connection state; it is released before any await or network request. Queries during reconnect wait for subscription and flow setup to finish. Failed or cancelled reconnects resolve those waits with an error; dropping the engine closes the shared state.

The delivery and event loops are unchanged from master. Acknowledgements, redelivery, and lifecycle operations keep their existing ordering, including ack-before-close. There are no new tasks, dependencies, or public APIs. A query can still encounter a failed connection before reconnect starts; this PR does not add automatic retries.

Testing

Ten regression tests cover queries under backpressure, message order, partial-batch replay, ack-before-close, send/flush timing, and connection state during reconnect and shutdown. On Pulsar 2.11.4, all 69 tests and 19 doctests pass; one existing doctest is ignored. Both Clippy configurations pass. Additional Tokio and async-std checks verified all 31 unread batch records survived reconnect and 20 ack-then-close cycles per runtime left no backlog. Local builds used installed protoc instead of protobuf-src.

Throughput measurements remain inconclusive. The delivery loop adds no per-message work, but local timings varied widely and the unbatched comparison reversed on a repeat run. These results do not establish performance neutrality.

Local throughput measurements

Release builds, 20,000 records, receive/flow windows of 1,000. Alternating run order; all runs verified exact message order and broker backlog zero. Times below are median receive + ack-enqueue milliseconds, with ranges in parentheses.

Workload Runs per version Master This PR
Batches of 100 5 462 (420–878) 534 (404–624)
Unbatched, initial 3 491 (453–1358) 1673 (1389–2227)
Unbatched, repeat 5 1422 (447–2277) 461 (379–1692)

Before the repeat, both binaries were rebuilt with the same harness, lockfile, features, and toolchain; they matched the original binaries byte for byte. The broker ran under amd64 emulation on an arm64 host. This is not a production capacity benchmark.

Related: #412 addresses backpressure at the connection layer. The acknowledgement work discussed in #175, #428, and #162 remains separate; this PR does not claim to resolve those issues.

@kacper-li-airspace-intelligence
kacper-li-airspace-intelligence marked this pull request as ready for review September 8, 2026 14:04
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