feat: add max_retry to drop a batch after too many failed retries - #118
Merged
Conversation
Add a new producer option `max_retry` (default `infinity`, i.e. retry forever). When set to a non-negative integer, a batch that keeps receiving Kafka error responses (e.g. `not_leader_for_partition`) is dropped once its attempt counter reaches `max_retry + 1` — the initial send plus `max_retry` retries have all failed. `max_retry = 0` drops on the first error. The check is applied in the Kafka-error path of `do_handle_kafka_ack/3`: when the front in-flight request has been attempted enough times, it is popped and its callers are acked with reason `max_retry_exceeded` (via `clear_sent_and_ack_callers/3`) and the `dropped` counter is bumped, instead of incrementing the attempt counter and retrying. The producer still reconnects afterwards, since the error means the current connection is stale for the remaining in-flight requests. This bounds retries on Kafka error responses only; resends triggered purely by connection loss are bounded by `max_batch_age`, not `max_retry`.
zmstone
force-pushed
the
260719-max-retry
branch
from
July 19, 2026 08:44
9b8663f to
8fe4827
Compare
ieQu1
approved these changes
Jul 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add a new producer option
max_retry(defaultinfinity, i.e. retry forever).Motivation
Today wolff retries a batch indefinitely on Kafka error responses (e.g.
not_leader_for_partition). There is no way to cap the number of retries and give up on a batch.max_batch_age(added in 4.2.0) bounds time, but some callers want to bound the retry count on error responses.What this does
When
max_retryis set to a non-negative integer, a batch is dropped once its attempt counter reachesmax_retry + 1— i.e. the initial send plusmax_retryretries have all failed:max_retry = 0→ drop on the first error response.max_retry = 3→ drop after the 4th failed attempt (3 retries).infinity(default) → retry forever (unchanged behavior).The check lives in the Kafka-error path of
do_handle_kafka_ack/3. When the front in-flight request has been attempted enough times, it is popped and its callers are acked with reasonmax_retry_exceeded(via the existingclear_sent_and_ack_callers/3, which also bumpsfailed/retried_failed), and thedroppedcounter is bumped — instead of incrementing the attempt counter and retrying. The producer still reconnects afterwards, since the error (e.g.not_leader_for_partition) means the current connection is stale for the remaining in-flight requests.Scope / notes
attemptscounter and are bounded bymax_batch_age, notmax_retry. The two options are complementary (time-based vs error-count-based).max_retry_exceededreaches the ack callback; downstream callers that pattern-match ack results should add a clause for it.Tests
is_max_retry_reached_test_/0— pure unit tests of the boundary (infinity,0, and themax_retry + 1edge).drop_batch_on_max_retry_test_/0— withmax_retry = 0, injects anot_leader_for_partitionproduce response and asserts the batch is dropped (ackmax_retry_exceeded,droppedbumped) rather than retried.Ran
rebar3 eunitlocally: the new tests pass; the only failures are 4 pre-existing environment-specific tests (message_too_large,record_list_too_large,one_byte_limit,leader_restart) that also fail on unmodifiedmainin this environment and pass in CI.