Skip to content

[GSoC 2026] Kafka Streams runner: user documentation, marked experimental - #39627

Open
junaiddshaukat wants to merge 2 commits into
apache:feat/18479-kafka-streams-runner-skeletonfrom
junaiddshaukat:feat/ks-usage-guide
Open

[GSoC 2026] Kafka Streams runner: user documentation, marked experimental#39627
junaiddshaukat wants to merge 2 commits into
apache:feat/18479-kafka-streams-runner-skeletonfrom
junaiddshaukat:feat/ks-usage-guide

Conversation

@junaiddshaukat

Copy link
Copy Markdown
Contributor

Summary

Part of #18479.

Adds the runner's user documentation and marks it experimental, which was the remaining documentation deliverable. Reviewing #39611 the point came up that the features which are core but not yet implemented must be written down; this is where they are.

The documentation

website/www/site/content/en/documentation/runners/kafkastreams.md, linked from the runners menu alongside the others. It covers what the runner is and why someone would pick it, how to start the job server and submit a pipeline, every pipeline option with its default, the internal topics it creates, and two lists that matter more than the rest: what is supported and what is not.

The unsupported list is deliberately specific rather than a general disclaimer, and says what each gap means for a user:

  • side inputs; stateful ParDo and user timers; merging windows, so no session windows; custom WindowFns; splittable DoFn; TestStream
  • reading a source in parallel — a source is split into exactly one part, and one that insists on splitting further is rejected rather than silently truncated
  • maxBundleTimeMs is accepted but has no effect, because closing a bundle from a wall-clock punctuator duplicated output against a real broker and the cause is not yet understood
  • finalizeCheckpoint is not called, so a source relying on finalization to acknowledge data will not see it
  • only attempted metrics, not committed

Marking it experimental

KafkaStreamsRunner's javadoc now opens by saying the runner is experimental, naming the main gaps and warning that behaviour and options may change, with links to the documentation and the tracking issue. The documentation says the same in its own section, so someone arriving from either direction learns it before they invest in it.

A task to start the job server

The documentation needs a command that works, and there wasn't one — the job server could only be started by invoking KafkaStreamsJobServerDriver directly. :runners:kafka-streams:runJobServer now does it, with arguments passed through -PjobServerArgs. Verified by running it: the job service comes up on localhost:8099 and artifact staging on localhost:8098, which is what the documentation tells the reader to expect.

Testing

The runner code change is javadoc only; the gate is unchanged and still green.

./gradlew :runners:kafka-streams:validatesRunner   # 59 tests, 0 failures
./gradlew :runners:kafka-streams:build            # 86 unit tests, spotless + checker + errorprone

…ntal

Adds the runner's documentation page, linked from the runners menu: what the
runner is and why someone would choose it, how to start the job server and
submit a pipeline, every pipeline option with its default, the internal
topics it creates, and what is and is not supported.

The unsupported list is specific rather than a general disclaimer, since
these are core parts of the Beam model rather than nice-to-haves: side
inputs, stateful ParDo and user timers, merging windows, custom WindowFns,
splittable DoFn, TestStream, reading a source in parallel, the bundle time
bound, finalizeCheckpoint, and committed metrics. Each says what it means for
a user.

KafkaStreamsRunner's javadoc now opens by saying the runner is experimental,
naming the main gaps and warning that behaviour and options may change, so
the caveat is visible from the code as well as the website.

Adds :runners:kafka-streams:runJobServer, because the documentation needs a
command that works and the job server could previously only be started by
invoking its driver class directly.

@je-ik je-ik 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.

Can we also update capability matrix?

website/www/site/data/capability_matrix.yaml

--runner=PortableRunner \
--jobEndpoint=localhost:8099 \
--bootstrapServers=localhost:9092 \
--applicationId=my-beam-pipeline

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.

We probably should provide a "wrappers" as flink does that will run their own jobserver automatically.

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.

Good catch, and it turned out we already have one — I'd just documented the wrong path. KafkaStreamsRunner.run() starts a KafkaStreamsJobServerDriver on a dynamic port when jobEndpoint is empty, and stops it when the pipeline finishes, so from Java there is nothing to start by hand.

The page now leads with --runner=KafkaStreamsRunner for that, and keeps the manual job server as what you would use from another SDK or against a shared deployment. My original text only showed the manual route, which made the runner look more awkward to use than it is.

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.

Flink adds a similar wrapper for python (and maybe go as well?), you can check it for inspiration.

Comment thread website/www/site/content/en/documentation/runners/kafkastreams.md
Documents that the runner starts its own job server. Selecting
KafkaStreamsRunner with no jobEndpoint set brings one up on a dynamic port
and shuts it down with the pipeline, so nothing has to be started by hand
from Java; the manual job server is now what another SDK or a shared
deployment uses.

Links a tracking issue against each unimplemented feature, so the list says
where to follow up rather than only what is absent.

Adds the runner to the capability matrix, with an entry in each capability
rather than only the column. The partial ones say what the limit is: the
source API is read by a single reader, metrics are attempted only, and
event-time triggering covers the default trigger.
@junaiddshaukat

Copy link
Copy Markdown
Contributor Author

Also Added, in capability_matrix.yaml. The runner is now a column and has an entry in all 38 capabilities rather than just the header, so it doesn't show up as blanks.

I kept the partial ones honest rather than optimistic: Source API is "Partially" because we read with a single reader, Metrics is "Partially" for attempted-only, and event-time triggers is "Partially" since only the default trigger is exercised. Everything else is a straight Yes or No against what the ValidatesRunner suite actually covers. The diff is additions only — no existing runner's entries were touched.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Assigning reviewers:

R: @damccorm for label website.

Note: If you would like to opt out of this review, comment assign to next reviewer.

Available commands:

  • stop reviewer notifications - opt out of the automated review tooling
  • remind me after tests pass - tag the comment author after tests pass
  • waiting on author - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)

The PR bot will only process comments in the main thread (not review comments).

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.

2 participants