This is an automated email from the ASF dual-hosted git repository.

je-ik pushed a commit to branch feat/18479-kafka-streams-runner-skeleton
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to 
refs/heads/feat/18479-kafka-streams-runner-skeleton by this push:
     new 49d459a243e [GSoC 2026] Kafka Streams runner: put the runner behind an 
opt-in build flag (#39762)
49d459a243e is described below

commit 49d459a243eb613e97e6dae5e935638d8e4f4677
Author: M Junaid Shaukat <[email protected]>
AuthorDate: Sun Aug 16 22:43:37 2026 +0500

    [GSoC 2026] Kafka Streams runner: put the runner behind an opt-in build 
flag (#39762)
---
 .../beam_KafkaStreamsRunner_FeatureBranch.yml      |  4 +--
 .../beam_PreCommit_Java_Kafka_Streams_Runner.yml   |  1 +
 build.gradle.kts                                   |  5 ++-
 sdks/python/test-suites/portable/common.gradle     | 10 ++++--
 settings.gradle.kts                                | 14 ++++++--
 .../en/documentation/runners/kafkastreams.md       | 40 +++++++++++++++++++---
 6 files changed, 61 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/beam_KafkaStreamsRunner_FeatureBranch.yml 
b/.github/workflows/beam_KafkaStreamsRunner_FeatureBranch.yml
index e290c9beee1..8b558865c21 100644
--- a/.github/workflows/beam_KafkaStreamsRunner_FeatureBranch.yml
+++ b/.github/workflows/beam_KafkaStreamsRunner_FeatureBranch.yml
@@ -69,6 +69,6 @@ jobs:
           restore-keys: |
             ${{ runner.os }}-gradle-kafka-streams-
       - name: Build and test Kafka Streams runner
-        run: ./gradlew :runners:kafka-streams:build --no-daemon --stacktrace
+        run: ./gradlew -Pwith-kafka-streams-runner 
:runners:kafka-streams:build --no-daemon --stacktrace
       - name: Run ValidatesRunner suite
-        run: ./gradlew :runners:kafka-streams:validatesRunner --no-daemon 
--stacktrace
+        run: ./gradlew -Pwith-kafka-streams-runner 
:runners:kafka-streams:validatesRunner --no-daemon --stacktrace
diff --git a/.github/workflows/beam_PreCommit_Java_Kafka_Streams_Runner.yml 
b/.github/workflows/beam_PreCommit_Java_Kafka_Streams_Runner.yml
index 564b2bbc4bc..005764b4d33 100644
--- a/.github/workflows/beam_PreCommit_Java_Kafka_Streams_Runner.yml
+++ b/.github/workflows/beam_PreCommit_Java_Kafka_Streams_Runner.yml
@@ -89,6 +89,7 @@ jobs:
         uses: ./.github/actions/gradle-command-self-hosted-action
         with:
           gradle-command: :runners:kafka-streams:build
+          arguments: -Pwith-kafka-streams-runner
           max-workers: 4
       - name: Archive JUnit Test Results
         uses: actions/upload-artifact@v7
diff --git a/build.gradle.kts b/build.gradle.kts
index b3b9fdd7fdf..3f5d39d9934 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -278,7 +278,10 @@ tasks.register("javaPreCommit") {
   dependsOn(":runners:java-fn-execution:build")
   dependsOn(":runners:java-job-service:build")
   dependsOn(":runners:jet:build")
-  dependsOn(":runners:kafka-streams:build")
+  // Only when the opt-in flag put it in the build; see settings.gradle.kts.
+  if (findProject(":runners:kafka-streams") != null) {
+    dependsOn(":runners:kafka-streams:build")
+  }
   dependsOn(":runners:local-java:build")
   dependsOn(":runners:portability:java:build")
   dependsOn(":runners:prism:java:build")
diff --git a/sdks/python/test-suites/portable/common.gradle 
b/sdks/python/test-suites/portable/common.gradle
index c8c789ca96d..6cc30fcadab 100644
--- a/sdks/python/test-suites/portable/common.gradle
+++ b/sdks/python/test-suites/portable/common.gradle
@@ -203,10 +203,14 @@ def createKafkaStreamsRunnerTestTask() {
   return task
 }
 
-createKafkaStreamsRunnerTestTask()
+// The Kafka Streams runner is opt-in (-Pwith-kafka-streams-runner), so its 
job server is only a
+// project when it was asked for; without it there is nothing for these tasks 
to run against.
+if (project.findProject(':runners:kafka-streams:job-server') != null) {
+  createKafkaStreamsRunnerTestTask()
 
-tasks.register("kafkaStreamsValidatesRunner") {
-  dependsOn 'kafkaStreamsCompatibilityMatrixLOOPBACK'
+  tasks.register("kafkaStreamsValidatesRunner") {
+    dependsOn 'kafkaStreamsCompatibilityMatrixLOOPBACK'
+  }
 }
 
 def createPrismRunnerTestTask(String workerType) {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index cd1134d685c..050d97dc600 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -143,9 +143,17 @@ 
include(":runners:google-cloud-dataflow-java:examples-streaming")
 include(":runners:java-fn-execution")
 include(":runners:java-job-service")
 include(":runners:jet")
-include(":runners:kafka-streams")
-include(":runners:kafka-streams:proto")
-include(":runners:kafka-streams:job-server")
+// The Kafka Streams runner is opt-in, and is left out of the build unless it 
is asked for with
+// -Pwith-kafka-streams-runner. It is being developed in the open so that 
others can build it and
+// work on it, but it is not ready to be released: bundles are not yet closed 
after a bounded time
+// (https://github.com/apache/beam/issues/39633), among other things. Keeping 
it out of the default
+// build means it reaches nobody who did not ask for it, and the flag can be 
dropped when the runner
+// is stable enough - or the runner can be dropped, without either affecting 
users.
+if (startParameter.projectProperties.containsKey("with-kafka-streams-runner")) 
{
+    include(":runners:kafka-streams")
+    include(":runners:kafka-streams:proto")
+    include(":runners:kafka-streams:job-server")
+}
 include(":runners:local-java")
 include(":runners:portability:java")
 include(":runners:prism")
diff --git a/website/www/site/content/en/documentation/runners/kafkastreams.md 
b/website/www/site/content/en/documentation/runners/kafkastreams.md
index 058e85b6d46..1fe5d4e86ca 100644
--- a/website/www/site/content/en/documentation/runners/kafkastreams.md
+++ b/website/www/site/content/en/documentation/runners/kafkastreams.md
@@ -31,7 +31,7 @@ groups, changelog topics, and transactions.
 That makes it worth considering if you already run Kafka and want Beam's 
programming model without
 introducing a second distributed system to operate.
 
-## The runner is experimental
+## The runner is experimental, and is not built by default
 
 **The Kafka Streams Runner is experimental.** It executes a meaningful subset 
of the Beam model
 correctly, and the parts it does support are covered by Beam's own 
`@ValidatesRunner` suite, but
@@ -41,6 +41,36 @@ supported](#what-is-not-supported-yet) before choosing it 
for anything real.
 It is also aimed squarely at streaming. A pipeline over bounded data will run, 
but there are more
 efficient choices for batch work; this runner exists for pipelines that do not 
end.
 
+It is **not part of a Beam release, and not part of the default build**. It is 
developed in the open
+so that people can build it, use it and work on it, but it is not ready to be 
released: there are
+known bugs, not only missing features — bundles are not yet closed after a 
bounded time
+([#39633](https://github.com/apache/beam/issues/39633)), for one. Building it 
takes an opt-in flag:
+
+```
+./gradlew -Pwith-kafka-streams-runner :runners:kafka-streams:build
+```
+
+Without `-Pwith-kafka-streams-runner` the runner's projects are left out of 
the build entirely, so
+it reaches nobody who has not asked for it. The intent is to give the runner 
somewhere to be
+developed and maintained by whoever is interested in it. If it becomes stable 
enough the flag will
+be dropped and the runner built like any other; if it does not, it can be 
removed again without
+affecting anyone, since no release ever contained it.
+
+## Building it
+
+Every command in this page needs the opt-in flag. To build the runner and run 
its tests:
+
+```
+./gradlew -Pwith-kafka-streams-runner :runners:kafka-streams:build
+./gradlew -Pwith-kafka-streams-runner :runners:kafka-streams:validatesRunner
+```
+
+To build the job server jar that the Python SDK submits to:
+
+```
+./gradlew -Pwith-kafka-streams-runner 
:runners:kafka-streams:job-server:shadowJar
+```
+
 ## Running a pipeline
 
 The runner is portable: it executes user code over the Fn API, in an SDK 
harness, so a pipeline goes
@@ -74,14 +104,14 @@ python my_pipeline.py \
 
 The SDK harness runs in `LOOPBACK` mode by default, so a local run needs no 
Docker. Building the jar
 takes a while the first time; `--kafka_streams_job_server_jar` points at a 
prebuilt one, which
-`./gradlew :runners:kafka-streams:job-server:shadowJar` produces.
+`./gradlew -Pwith-kafka-streams-runner 
:runners:kafka-streams:job-server:shadowJar` produces.
 
 ### Against a job server you are already running
 
 Start one, which listens on `localhost:8099` by default:
 
 ```
-./gradlew :runners:kafka-streams:runJobServer
+./gradlew -Pwith-kafka-streams-runner :runners:kafka-streams:runJobServer
 ```
 
 Then point a pipeline at it instead of letting the runner start its own. From 
Java:
@@ -117,10 +147,12 @@ Named as Java spells them below; from Python the same 
options are in snake case,
 | `applicationId` | *(required)* | Kafka Streams `application.id`. Must be 
unique per pipeline. |
 | `internalParallelism` | `1` | Partitions for the internal topics the runner 
creates, which is the parallelism the shuffled parts of a pipeline can reach. |
 | `topicReplicationFactor` | `1` | Replication factor for those topics. |
-| `maxBundleSize` | `1000` | Elements per bundle, and elements taken per poll 
of an unbounded source. |
+| `maxBundleSize` | `1000` | Elements per bundle. |
 | `maxBundleTimeMs` | `1000` | Intended cap on how long a bundle may stay 
open. **Not applied yet** — see below. |
+| `readMaxElementsPerPoll` | `1000` | Elements an unbounded source may take 
per poll. Separate from `maxBundleSize`, so a pipeline can have small bundles 
without throttling its source. |
 | `readMaxPollTimeMs` | `10` | How long one turn of reading an unbounded 
source may take before it yields the Kafka Streams thread. A source is polled 
every 50ms and shares its thread with the rest of the topology, so a turn that 
overruns that interval leaves the stages below it unscheduled; a bound on 
elements alone cannot bound the time. |
 | `readCheckpointNumBundles` | `10` | Polls of an unbounded source between 
stores of its checkpoint mark. Larger values replay more after a restart. |
+| `sessionTimeoutMs` | `45000` | How long the consumer group waits before 
deciding an instance has gone, which is the floor on how quickly its work moves 
elsewhere. A broker refuses a value below its own 
`group.min.session.timeout.ms`. |
 | `stateDir` | temp directory | Where Kafka Streams keeps local state. |
 
 ### Topics the runner creates

Reply via email to