Skip to content

KAFKA-20772 (1/n): Add DLQ system tests for single-partition share group scenarios#22786

Open
sjhajharia wants to merge 5 commits into
apache:trunkfrom
sjhajharia:KAFKA-20772
Open

KAFKA-20772 (1/n): Add DLQ system tests for single-partition share group scenarios#22786
sjhajharia wants to merge 5 commits into
apache:trunkfrom
sjhajharia:KAFKA-20772

Conversation

@sjhajharia

@sjhajharia sjhajharia commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

This adds the first system-test coverage for share group dead-letter
queues (KIP-1191, part of KAFKA-19469), plus the client-side tooling
changes needed to drive it — there was previously no way for any
ducktape test client to explicitly REJECT or RELEASE a share-consumed
record; VerifiableShareConsumer only ever implicitly accepted.

VerifiableShareConsumer.java

  • New --ack-pattern CLI flag: a comma-separated cycle of
    accept|release|reject|renew, applied per record via (offset % pattern.length) — keyed off the immutable record offset so the
    assignment is stable across redeliveries.
  • When set, the consumer is switched to
    share.acknowledgement.mode=explicit and requires
    --acknowledgement-mode sync|async (rejects auto at arg-parse time,
    since explicit per-record acks still need a commit to ship).
  • offsets_acknowledged events now optionally include an
    ackTypeCounts breakdown ({"ACCEPT": n, "RELEASE": n, ...}), omitted
    entirely when --ack-pattern isn't used — no change to the existing
    JSON schema for any current caller.

verifiable_share_consumer.py (ducktape service)

  • Plumbs ack_pattern through to the CLI, and adds
    total_accepted()/total_released()/total_rejected()/total_renewed()
    accessors backed by the new ackTypeCounts data.

kafka.py

  • set_share_group_dlq_config(group, topic_name, copy_record_enable)
    sets the GroupConfig DLQ configs via kafka-configs.sh.
  • set_share_group_delivery_count_limit(group, limit) — sets
    share.delivery.count.limit (the per-group override).
  • New share_version constructor param to bootstrap a cluster with
    --feature share.version=<n>. Since DLQ (share.version=2) is above
    ShareVersion.LATEST_PRODUCTION, this also flips on
    unstable.feature.versions.enable in the broker properties.

New: tests/kafkatest/tests/client/share_consumer_dlq_test.py
Three tests on a real 3-broker isolated-KRaft cluster, verifying actual
DLQ topic content (not just consumer-side counters):

  • test_single_partition_dlq_reject — every record REJECTed, DLQ'd
    exactly once, values null (copy-record disabled, the default).
  • test_single_partition_dlq_release — every record RELEASEd
    repeatedly; once delivery count exceeds a lowered
    share.delivery.count.limit, it lands in the DLQ.
  • test_single_partition_dlq_mixed — records cycled
    reject/release/accept by offset % 3, copy-record enabled; asserts the
    DLQ'd record set and values exactly match the subset of produced values
    that should have been rejected/released (cross-checked against
    VerifiableProducer.acked_values, not just "value is non-null").

All three verified passing end-to-end against a live ducker cluster
(tests/docker/run_tests.sh).

> TC_PATHS="tests/kafkatest/tests/client/share_consumer_dlq_test.py"
bash tests/docker/run_tests.sh

================================================================================
SESSION REPORT (ALL TESTS)
ducktape version: 0.14.0
session_id:       2026-07-08--005
run time:         5 minutes 27.339 seconds
tests run:        6
passed:           6
flaky:            0
failed:           0
ignored:          0
================================================================================
test_id:
kafkatest.tests.client.share_consumer_dlq_test.ShareConsumerDLQTest.test_single_partition_dlq_mixed.metadata_quorum=COMBINED_KRAFT
status:     PASS
run time:   45.786 seconds
--------------------------------------------------------------------------------
test_id:
kafkatest.tests.client.share_consumer_dlq_test.ShareConsumerDLQTest.test_single_partition_dlq_mixed.metadata_quorum=ISOLATED_KRAFT
status:     PASS
run time:   1 minute 5.269 seconds
--------------------------------------------------------------------------------
test_id:
kafkatest.tests.client.share_consumer_dlq_test.ShareConsumerDLQTest.test_single_partition_dlq_reject.metadata_quorum=COMBINED_KRAFT
status:     PASS
run time:   43.421 seconds
--------------------------------------------------------------------------------
test_id:
kafkatest.tests.client.share_consumer_dlq_test.ShareConsumerDLQTest.test_single_partition_dlq_reject.metadata_quorum=ISOLATED_KRAFT
status:     PASS
run time:   1 minute 2.872 seconds
--------------------------------------------------------------------------------
test_id:
kafkatest.tests.client.share_consumer_dlq_test.ShareConsumerDLQTest.test_single_partition_dlq_release.metadata_quorum=COMBINED_KRAFT
status:     PASS
run time:   43.429 seconds
--------------------------------------------------------------------------------
test_id:
kafkatest.tests.client.share_consumer_dlq_test.ShareConsumerDLQTest.test_single_partition_dlq_release.metadata_quorum=ISOLATED_KRAFT
status:     PASS
run time:   1 minute 5.794 seconds
--------------------------------------------------------------------------------

Reviewers: Sushant Mahajan smahajan@confluent.io, Chia-Ping Tsai
chia7712@gmail.com

@github-actions github-actions Bot added triage PRs from the community tools labels Jul 8, 2026
@smjn smjn requested a review from Copilot July 8, 2026 06:45
@smjn smjn added KIP-932 Queues for Kafka ci-approved and removed triage PRs from the community labels Jul 8, 2026

@smjn smjn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add combined_kraft as well in the matrix

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds end-to-end ducktape system test coverage for share group dead-letter queues (DLQ, KIP-1191) in a single-partition scenario, along with the supporting test harness/tooling needed to drive explicit per-record share acknowledgements and to bootstrap clusters with share.version=2.

Changes:

  • Extend VerifiableShareConsumer with an --ack-pattern flag for per-record explicit ack cycling and optional ackTypeCounts reporting in offsets_acknowledged events.
  • Enhance ducktape’s verifiable_share_consumer.py service to pass ack_pattern through and expose per-ack-type counters.
  • Add KafkaService helpers to configure share group DLQ settings and to bootstrap share.version, plus new DLQ-focused system tests.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
tools/src/main/java/org/apache/kafka/tools/VerifiableShareConsumer.java Adds --ack-pattern explicit-ack behavior and optional ack-type breakdown in emitted events.
tests/kafkatest/services/verifiable_share_consumer.py Plumbs ack_pattern into the CLI and aggregates ackTypeCounts into helper counters.
tests/kafkatest/services/kafka/kafka.py Adds share-version bootstrapping and new helpers to configure share group DLQ + delivery-count-limit.
tests/kafkatest/tests/client/share_consumer_dlq_test.py New ducktape system tests validating DLQ topic contents for reject/release/mixed patterns.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +668 to +674
List<AcknowledgeType> ackPattern = parseAckPattern(res.getString("ackPattern"));
if (!ackPattern.isEmpty()) {
if (acknowledgementMode == AcknowledgementMode.AUTO) {
throw new ArgumentParserException(
"--ack-pattern requires --acknowledgement-mode to be 'sync' or 'async', not 'auto'", parser);
}
}
Comment thread tests/kafkatest/services/kafka/kafka.py
@sjhajharia sjhajharia requested a review from smjn July 8, 2026 12:17
@smjn

smjn commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Mostly good, one AI comment seems relevant and could result in flakiness. Please look into it.

@smjn smjn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI comment regarding unchecked map creation overriding previous values could result in flakiness. Please address

@sjhajharia sjhajharia requested a review from smjn July 9, 2026 06:14

@chia7712 chia7712 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sjhajharia thanks for this patch!

partitionOffsets.add(record.offset());

if (!ackPattern.isEmpty()) {
AcknowledgeType type = ackPattern.get((int) (record.offset() % ackPattern.size()));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if ackPattern contains RENEW?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review. I have added the support for RENEW as well.

Comment thread tools/src/main/java/org/apache/kafka/tools/VerifiableShareConsumer.java Outdated
.metavar("ACKNOWLEDGEMENT-MODE")
.help("Acknowledgement mode for the share consumers (must be either 'auto', 'sync' or 'async')");

parser.addArgument("--ack-pattern")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add those new options to KIP-1191? Or is it fine since this is a test class?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think given its an internal class which we use only for our system tests and do not expose it to customers, we shall be good to go ahead in this state. Still, I am open to the other way round too if you think necessary.

@sjhajharia sjhajharia requested a review from chia7712 July 10, 2026 04:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants