Skip to content

feat: [Phase 1 - Draft] Queue Semantics support in Kafka Ingestion#19311

Open
Shekharrajak wants to merge 49 commits into
apache:masterfrom
Shekharrajak:feature/kafka-share-group-ingestion
Open

feat: [Phase 1 - Draft] Queue Semantics support in Kafka Ingestion#19311
Shekharrajak wants to merge 49 commits into
apache:masterfrom
Shekharrajak:feature/kafka-share-group-ingestion

Conversation

@Shekharrajak
Copy link
Copy Markdown
Contributor

@Shekharrajak Shekharrajak commented Apr 14, 2026

Phase 1 #18439.

Description

Fixed the bug ...

Renamed the class ...

Added a forbidden-apis entry ...

Release note


Key changed/added classes in this PR
  • MyFoo
  • OurBar
  • TheirBaz

This PR has:

  • been self-reviewed.
  • added documentation for new or modified features or behaviors.
  • a release note entry in the PR description.
  • added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
  • added or updated version, license, or notice information in licenses.yaml
  • added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold for code coverage is met.
  • added integration tests.
  • been tested in a test Druid cluster.

Demo

https://youtu.be/K_O1MH-AaE8

cd apache-druid-31.0.0

# Replace the kafka extension with our build
rm extensions/druid-kafka-indexing-service/*.jar
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can build from the source and use the tar

agg -> agg.hasSumAtLeast(numRecords)
);

Assertions.assertEquals(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Making sure we read all the records.

@Shekharrajak Shekharrajak force-pushed the feature/kafka-share-group-ingestion branch from d31199b to 4a30bee Compare May 8, 2026 06:17
@Shekharrajak
Copy link
Copy Markdown
Contributor Author

Spending time on Integeration testing embedded-tests/src/test/java/org/apache/druid/testing/embedded/indexing/EmbeddedShareGroupIngestionTest.java

@Shekharrajak Shekharrajak changed the title [DRAFT] Queue Semantics support in Kafka Ingestion feat: [Phase 1 - Draft] Queue Semantics support in Kafka Ingestion May 8, 2026
@Shekharrajak
Copy link
Copy Markdown
Contributor Author

For smaller blast radius and clean separation - parking the suggestion #18439 (comment) , Also KafkaShareGroupSupervisor (planned) will be structurally different from KafkaSupervisor — no partition-to-task assignment, no offset bookkeeping, seek/rest .

}

@Test
public void test_shareGroupIngestion_basicEndToEnd() throws InterruptedException
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Subscribe to topic with KafkaShareConsumer (groupId), poll → parse (CSV) → persist → publish → acknowledge(ACCEPT) → commitSync → broker offset persistence. SQL COUNT(*) == 10.

final int numRecords = 5;
final int rowsPerRecord = 4;
kafkaServer.produceRecordsToTopic(
generateMultiObjectJsonRecords(topic, numRecords, rowsPerRecord, DateTimes.of("2025-07-01"))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

StreamChunkReader multi-row path One Kafka record carrying 4 whitespace-separated JSON objects produces 4 rows. SQL count = numRecords × rowsPerRecord (5 × 4 = 20). Verifies no row is dropped before ACK.

@Shekharrajak
Copy link
Copy Markdown
Contributor Author

To make sure no data loss we are ack only after the publish completed https://github.com/apache/druid/pull/19311/changes#diff-487176908fb14d87486db6f683c9ddb34465f3a1572f5c01b11d7b9c6a482289R381

Although this will be slow and no concurrency but I think for the intial phase this is fine and we can improve the performance step by step.

WDYT @gianm @a2l007 @clintropolis @FrankChen021 ?

@Shekharrajak
Copy link
Copy Markdown
Contributor Author

CI checks are failing due to one flaky test unrelated to this PR : #19435

recordMap.put(new TopicPartition("test-topic", 0), recordsP0);
recordMap.put(new TopicPartition("test-topic", 1), recordsP1);
Mockito.when(mockConsumer.poll(Mockito.any(Duration.class)))
.thenReturn(new ConsumerRecords<>(recordMap));
final Map<TopicPartition, List<ConsumerRecord<byte[], byte[]>>> recordMap = new HashMap<>();
recordMap.put(new TopicPartition(record.topic(), record.partition()), List.of(record));
Mockito.when(mockConsumer.poll(Mockito.any(Duration.class)))
.thenReturn(new ConsumerRecords<>(recordMap));
*/
Map<PartitionIdType, Optional<Exception>> commitSync();

Set<PartitionIdType> getPartitionIds(String stream);
@Shekharrajak Shekharrajak force-pushed the feature/kafka-share-group-ingestion branch from 234a8ec to e5894ef Compare May 9, 2026 05:36
Copy link
Copy Markdown
Member

@FrankChen021 FrankChen021 left a comment

Choose a reason for hiding this comment

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

Severity Findings
P0 0
P1 0
P2 2
P3 0
Total 2

Reviewed 22 of 22 changed files. Findings focus on task scheduling semantics and Kafka compatibility test coverage.


This is an automated review by Codex GPT-5

<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/KafkaIndexTaskTest.java</exclude>
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.

[P2] Kafka compatibility tests are skipped globally

This Surefire exclusion removes the main KafkaIndexTask, KafkaRecordSupplier, KafkaSamplerSpec, and KafkaSupervisor test classes from every normal test run. Since this PR also upgrades kafka-clients to 4.2.0, those are the regression tests most likely to catch compatibility breaks in existing index_kafka ingestion; the new share-group mock and embedded tests do not cover that existing API surface. Please migrate or narrowly isolate the TestBroker-dependent cases instead of excluding the whole classes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, planning to fix (upgrade to 4.2 version in all places) as part of this #19322 - I feel that we need bunch of changes, API compatibility issues in running tests , kafka docker image for IT tests and in source code - so want to keep it in separate PR.

This PR mainly focus on Share group implementation.

@Shekharrajak
Copy link
Copy Markdown
Contributor Author

Struggling with CI check related to license :


Unsupported license: MPL 1.1
For:org.javassist javassist in: druid-kerberos
org.locationtech.jts jts-core in: parquet-extensions with: Eclipse Public License 2.0 ignoring Eclipse Distribution License - v 1.0
Error:  Command execution failed.
org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
    at org.apache.commons.exec.DefaultExecutor.executeInternal (DefaultExecutor.java:394)
    at org.apache.commons.exec.DefaultExecutor.execute (DefaultExecutor.java:292)
    at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:903)
    at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:863)
    at org.codehaus.mojo.exec.ExecMojo.execute (ExecMojo.java:454)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261)
[INFO] simple-client-sslcontext ........................... SUCCESS [  5.195 s]
[INFO] druid-basic-security ............................... SUCCESS [  9.326 s]
[INFO] druid-google-extensions ............................ SUCCESS [  7.697 s]
[INFO] druid-catalog ...................................... SUCCESS [  9.519 s]
[INFO] druid-testing-tools ................................ SUCCESS [  8.122 s]
[INFO] druid-testcontainers ............................... SUCCESS [  2.149 s]
[INFO] druid-influx-extensions ............................ SUCCESS [  4.579 s]
[INFO] druid-cassandra-storage ............................ SUCCESS [  3.987 s]
[INFO] dropwizard-emitter ................................. SUCCESS [  6.528 s]
[INFO] druid-cloudfiles-extensions ........................ SUCCESS [  5.857 s]
[INFO] druid-consul-extensions ............................ SUCCESS [  6.595 s]
[INFO] graphite-emitter ................................... SUCCESS [  6.085 s]
[INFO] druid-distinctcount ................................ SUCCESS [  4.219 s]
[INFO] druid-exact-count-bitmap ........................... SUCCESS [  7.275 s]
[INFO] statsd-emitter ..................................... SUCCESS [  6.282 s]
[INFO] druid-time-min-max ................................. SUCCESS [  5.725 s]
[INFO] druid-virtual-columns .............................. SUCCESS [  4.011 s]
[INFO] druid-thrift-extensions ............................ SUCCESS [  4.915 s]
[INFO] ambari-metrics-emitter ............................. SUCCESS [  6.306 s]
[INFO] sqlserver-metadata-storage ......................... SUCCESS [  6.266 s]
[INFO] kafka-emitter ...................................... SUCCESS [  6.186 s]
[INFO] druid-redis-cache .................................. SUCCESS [  7.346 s]
[INFO] druid-opentsdb-emitter ............................. SUCCESS [  5.524 s]
[INFO] druid-momentsketch ................................. SUCCESS [  6.063 s]
[INFO] druid-moving-average-query ......................... SUCCESS [  7.560 s]
[INFO] tdigestsketch ...................................... SUCCESS [  7.308 s]
[INFO] druid-ddsketch ..................................... SUCCESS [  7.400 s]
[INFO] druid-influxdb-emitter ............................. SUCCESS [  4.017 s]
[INFO] gce-extensions ..................................... SUCCESS [  6.621 s]
[INFO] aliyun-oss-extensions .............................. SUCCESS [  7.980 s]
[INFO] prometheus-emitter ................................. SUCCESS [  5.877 s]
[INFO] opentelemetry-emitter .............................. SUCCESS [  8.167 s]
[INFO] grpc-query ......................................... SUCCESS [ 14.755 s]
[INFO] druid-iceberg-extensions ........................... SUCCESS [  9.575 s]
[INFO] druid-deltalake-extensions ......................... SUCCESS [  6.163 s]
[INFO] druid-spectator-histogram .......................... SUCCESS [  8.500 s]
[INFO] druid-rabbit-indexing-service ...................... SUCCESS [  7.905 s]
[INFO] druid-ranger-security .............................. SUCCESS [  9.363 s]
[INFO] distribution ....................................... FAILURE [05:29 min]
[INFO] druid-quidem-ut .................................... SKIPPED
[INFO] druid-embedded-tests ............................... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  22:30 min
[INFO] Finished at: 2026-05-09T05:59:40Z
[INFO] ------------------------------------------------------------------------
Error:  Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.5.1:exec (check-licenses) on project distribution: Command execution failed. Process exited with an error: 1 (Exit value: 1) -> [Help 1]
Error:  
Error:  To see the full stack trace of the errors, re-run Maven with the -e switch.
Error:  Re-run Maven using the -X switch to enable full debug logging.
Error:  
Error:  For more information about the errors and possible solutions, please read the following articles:
Error:  [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
Error:  
Error:  After correcting the problems, you can resume the build with the command
Error:    mvn <args> -rf :distribution
Error: Process completed with exit code 1.

@Shekharrajak Shekharrajak force-pushed the feature/kafka-share-group-ingestion branch 2 times, most recently from e3a9ad7 to 7865104 Compare May 9, 2026 06:57
Copy link
Copy Markdown
Member

@FrankChen021 FrankChen021 left a comment

Choose a reason for hiding this comment

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

Reviewed 3 of 27 changed files. Follow-up review handled: the Kafka extension POM no longer has the global Surefire exclusions, and ShareGroupIndexTask now uses DEFAULT_REALTIME_TASK_PRIORITY with tests covering the default and context override cases.


This is an automated review by Codex GPT-5.5

@Shekharrajak Shekharrajak force-pushed the feature/kafka-share-group-ingestion branch from ede5072 to e159405 Compare May 13, 2026 17:45
@Shekharrajak Shekharrajak force-pushed the feature/kafka-share-group-ingestion branch from e159405 to 1a8bed2 Compare May 13, 2026 18:13
Copy link
Copy Markdown
Member

@FrankChen021 FrankChen021 left a comment

Choose a reason for hiding this comment

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

Severity Findings
P0 0
P1 0
P2 2
P3 0
Total 2

Reviewed 21 of 21 changed files.


This is an automated review by Codex GPT-5.5

Comment thread docs/ingestion/kafka-share-group-ingestion.md
final Map<TopicPartition, List<ConsumerRecord<byte[], byte[]>>> recordMap = new HashMap<>();
recordMap.put(new TopicPartition("test-topic", 0), List.of(record1));
recordMap.put(new TopicPartition("test-topic", 1), List.of(record2));
final ConsumerRecords<byte[], byte[]> consumerRecords = new ConsumerRecords<>(recordMap);
);
final Map<TopicPartition, List<ConsumerRecord<byte[], byte[]>>> recordMap = new HashMap<>();
recordMap.put(new TopicPartition("test-topic", 0), List.of(record));
when(mockConsumer.poll(any(Duration.class))).thenReturn(new ConsumerRecords<>(recordMap));
Copy link
Copy Markdown
Member

@FrankChen021 FrankChen021 left a comment

Choose a reason for hiding this comment

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

Follow-up handled. Reviewed 21 of 21 changed files. The demo now configures share.auto.offset.reset=earliest before producing sample records, and share-group consumer properties are sanitized again after dynamic config expansion. I do not have further inline replies on the two follow-up threads.


This is an automated review by Codex GPT-5.5

@Shekharrajak
Copy link
Copy Markdown
Contributor Author

Shekharrajak commented May 15, 2026

CI Check error - unrelated timeouts :

  embedded-tests/target/test-classes/org/apache/druid/testing/embedded/indexing/IngestionSmokeTest.class:282 | Timed out waiting for event after [20,000]ms 20.391s
  embedded-tests/target/test-classes/org/apache/druid/testing/embedded/indexing/IngestionSmokeTest.class:337 | Timed out waiting for event after [20,000]ms 20.015s
  embedded-tests/target/test-classes/org/apache/druid/testing/embedded/indexing/IngestionSmokeTest.class:166 | Timed out waiting for event after [20,000]ms 20.019s
  ℹ️ Posting with conclusion 'failure' to https://github.com/apache/druid/pull/19311 (sha: 2d094d5fbe6e11b6d22b1df8bf54c8cf7b7d03d2)
🚀 Publish results
  ℹ️ - Test Report - test-jdk25-[I*,A*,U*] - 18604 tests run, 17847 passed, 754 skipped, 3 failed.
     🧪 - embedded-tests/target/test-classes/org/apache/druid/testing/embedded/indexing/IngestionSmokeTest.class | Timed out waiting for event after [20,000]ms
     🧪 - embedded-tests/target/test-classes/org/apache/druid/testing/embedded/indexing/IngestionSmokeTest.class | Timed out waiting for event after [20,000]ms
     🧪 - embedded-tests/target/test-classes/org/apache/druid/testing/embedded/indexing/IngestionSmokeTest.class | Timed out waiting for event after [20,000]ms

Raised ticket #19463

@Shekharrajak
Copy link
Copy Markdown
Contributor Author

Another flaky test: #19464

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants