ProduceAsync and AckPolicy
Generated page
Model gemma-mtp, commit ef58254ca7be, 2026-08-16, sources: 6. Edit the code or the hand-written documentation instead.
Diagram
AckPolicy
The AckPolicy enumeration defines how the client waits for confirmation from the broker:
| Mode | Value | Description |
|---|---|---|
None | 0 | The broker answers nothing; the client receives no response and no offset. |
Written | 1 | The broker answers once the record is in the log, before any durability barrier. |
Forced | 2 | The broker answers after a force() operation (grouping all queued requests). |
ProduceAsync mechanics
The ProduceAsync method constructs a binary payload containing the topic name, partition ID, the chosen AckPolicy, and the list of records. The records are written to the partition such that they land contiguously, meaning one request results in a sequence of offsets from BaseOffset to LogEndOffset with no interleaving from other requests Connection.cs:183-213.
The write actor and batching
Performance is heavily dependent on how records are grouped. While Topic.SendAsync allows sending a single record, doing so one at a time is inefficient compared to using Connection.ProduceAsync with a list of records Connection.cs:382-387. In the Kotlin implementation, the batch function provides a way to collect records into a BatchScope to ensure they are sent as a single request, bypassing the standard accumulator to maintain the guarantee that records land contiguously Publishing.kt:85-99.
Failure modes and BrokerException
The client handles various broker responses. If a batch is empty or contains empty records, the broker may return a CORRUPT_REQUEST Connection.cs:178-180. If the broker refuses a request (e.g., UNKNOWN_TOPIC_OR_PARTITION), a BrokerException is thrown to the caller Connection.cs:131. Under AckPolicy.None, ProduceAsync returns null because no response is expected from the broker Connection.cs:214-216.
Recovery after a crash
Writes are not atomic. If a crash occurs mid-write, the system is designed so that recovery keeps the prefix of the batch that passed its checksums, meaning a partial batch can survive on its own Publishing.kt:76-79.
Connection integrity tests
The test suite ensures high reliability through several checks:
- Byte-for-byte delivery: Verifying that records arrive exactly as sent
ConnectionTests.cs:24-30. - Error propagation: Ensuring that a broker refusal is treated as a
BrokerExceptionbut does not close the connection, allowing for reuseConnectionTests.cs:56-64. - Protocol integrity: Confirming that a truncated response (e.g., due to a broker restart) results in a
ProtocolExceptionConnectionTests.cs:100-103.
Key files
| File | Lines | What is there |
|---|---|---|
…/Booblik/Connection.cs | 8-22 | AckPolicy enumeration definition |
…/Booblik/Connection.cs | 183-223 | ProduceAsync implementation and payload construction |
…/client/Publishing.kt | 85-99 | Producer.batch implementation for contiguous writes |
…/Booblik.Tests/ConnectionTests.cs | 24-31 | Tests for byte-for-byte record delivery |
…/Booblik.Tests/ConnectionTests.cs | 56-64 | Tests for error propagation and connection reuse |
…/Booblik.Tests/ConnectionTests.cs | 100-103 | Tests for truncated response handling |
…/benchmark/PartitionWriterBenchmark.kt | 92-102 | Benchmark for append performance and retention |
…/Booblik.Conformance/Program.cs | 127-138 | Conformance testing for Produce verb and AckPolicy.None |
Behaviour that not obvious
Connection.ProduceAsyncreturnsnullwhenAckPolicy.Noneis used, which can be interpreted as "no answer is coming"Connection.cs:214-216.- A
BrokerExceptiondoes not necessarily close theConnection; if the framing remains intact, the connection remains usable for subsequent requestsConnectionTests.cs:60-64. Topic.SendAsyncis a convenience method that wraps a single record into a list, which is significantly slower than batching multiple records in oneProduceAsynccallConnection.cs:382-387.