[runners-spark] Support stateful ParDo in the Structured Streaming batch runner - #39793
[runners-spark] Support stateful ParDo in the Structured Streaming batch runner#39793f-loris wants to merge 1 commit into
Conversation
6381ebc to
0318470
Compare
|
Checks are failing. Will not request review until checks are succeeding. If you'd like to override that behavior, comment |
0318470 to
d3b484c
Compare
|
Assigning reviewers: R: @Abacn for label java. Note: If you would like to opt out of this review, comment Available commands:
The PR bot will only process comments in the main thread (not review comments). |
Abacn
left a comment
There was a problem hiding this comment.
Thanks, could you please trigger the following postcommit tests:
https://github.com/apache/beam/actions/workflows/beam_PostCommit_Java_ValidatesRunner_Spark4.yml
by making any changes to these trigger files
-
.github/trigger_files/beam_PostCommit_Java_ValidatesRunner_SparkStructuredStreaming.json
-
.github/trigger_files/beam_PostCommit_Java_ValidatesRunner_Spark4.json
…tch runner Stateful, timer-using and @RequiresTimeSortedInput DoFns are dispatched to a new StatefulParDoTranslatorBatch, which groups by key and sorts each group by event time; StatefulDoFnGroupFunction then runs the DoFn per key with in-memory state and timers. Additional (tagged) outputs are encoded as one column per tag and split into per-tag datasets, mirroring the stateless multi-output translation in ParDoTranslatorBatch, keeping the single-output fast path. Requires Spark 3.4+ for KeyValueGroupedDataset#flatMapSortedGroups; earlier versions are rejected at translation time rather than failing mid-job. - Enable the UsesStatefulParDo, UsesKeyInParDo, UsesTimersInParDo, UsesMapState, UsesMultimapState, UsesSetState and UsesTimerMap ValidatesRunner categories for validatesStructuredStreamingRunnerBatch - Exclude UsesOrderedListState: every such test also uses @OnWindowExpiration, which is not supported - Exclude PerKeyOrderingTest#testMultipleStatefulOrdering* by name: they build on PeriodicImpulse and so are unbounded, but are not categorized as UsesUnboundedPCollections, and adding that category upstream would also stop other runners running them @OnWindowExpiration remains unsupported (apache#22524).
d3b484c to
10323df
Compare
|
@Abacn Thanks for your feedback. Updated the PR based an you comments and triggered the PostCommit runs you mentioned. |
Adds support for stateful ParDo — state, timers and
@RequiresTimeSortedInput— to the Spark Structured Streaming (Dataset-based) runner in batch mode, including additional (tagged) outputs.Fixes #39779
Approach
Stateful, timer-using and
@RequiresTimeSortedInputDoFns are dispatched to a newStatefulParDoTranslatorBatch, which groups by key viaKeyValueGroupedDataset#flatMapSortedGroupsand orders each group by event time.StatefulDoFnGroupFunctionthen runs theDoFnper key withInMemoryStateInternals/InMemoryTimerInternalsfromrunners-core.Because batch has no state store to bridge onto — state is a heap object scoped to a single key — every Beam state type is already implemented by
InMemoryStateInternals, so the state categories are enabled together rather than incrementally. Memory is bounded by the state one key holds rather than by that key's element count: groups stream off Spark's spillable sort instead of being materialized, unlike the classic runner's RDDgroupByKey.Sorting uses the
timestampcolumn of theWindowedValueencoder, which isLongTypeepoch millis, withasc_nulls_last: a null timestamp encodesEND_OF_WINDOW, which no concrete timestamp of the same window can exceed.The
DoFnis set up once per task and torn down from aTaskCompletionListener, with state, timers and a bundle per key.ValidatesRunner
Enabled for
validatesStructuredStreamingRunnerBatch:UsesStatefulParDo,UsesKeyInParDo,UsesTimersInParDo,UsesMapState,UsesMultimapState,UsesSetState,UsesOrderedListState,UsesTimerMap.Results on this branch:
:runners:spark:3:validatesStructuredStreamingRunnerBatch:runners:spark:4:validatesStructuredStreamingRunnerBatchAlso added: unit tests for translator dispatch and preconditions, and execution tests covering per-key state, state isolation across many keys in one partition,
@RequiresTimeSortedInputordering, event-time timers, looping timers,@FinishBundleordering relative to timers, and tagged outputs.Notes for reviewers
No CI covers this suite on Spark 4.
beam_PostCommit_Java_ValidatesRunner_Spark4runs:runners:spark:4:validatesRunner(the classic runner), andbeam_PostCommit_Java_ValidatesRunner_SparkStructuredStreamingis pinned to:runners:spark:3:.... This is pre-existing — the suite has never run on Spark 4 — so the 303/0 above was verified locally. Happy to add abeam_PostCommit_Java_ValidatesRunner_SparkStructuredStreaming4workflow here or as a follow-up if you'd like that coverage; it would be a near-copy of the existing one withjava-version: '17'.Spark 3.4+ requirement.
flatMapSortedGroupswas added in Spark 3.4, so stateful pipelines are rejected at translation time on 3.1–3.3 with a clear message rather than failing withNoSuchMethodErrormid-job. The stateful tests skip on those versions sosparkVersion31Test/sparkVersion33Teststay green.PerKeyOrderingTest#testMultipleStatefulOrdering*are excluded by name, not by category. They build onPeriodicImpulseand so are unbounded, but are not categorized asUsesUnboundedPCollections; adding that category upstream would also stop Dataflow and Flink running them, so the exclusion is kept local to this runner.The
ParDoTestOrderedListState range tests gainUsesOnWindowExpiration, which theirDoFns declare but which they were not categorized for. This is the one change outsiderunners/spark. It is a no-op for other runners: every runner excludingUsesOnWindowExpirationalso excludesUsesOrderedListState, so those tests did not run there.Deliberate mirroring of the stateless path.
createEncoders,createSideInputReader, the output receivers and the persist/split-by-tag block intentionally followParDoTranslatorBatch/DoFnPartitionIteratorFactory. Happy to consolidate into shared helpers if preferred.@OnWindowExpirationremains unsupported ([Feature Request]: Support onWindowExpiration in Spark runner so that GroupIntoBatches can be used #22524) and is rejected explicitly;UsesOnWindowExpirationstays excluded. Processing-time timers re-armed from@OnTimerdo not re-fire in batch, matching the classic runner; this is documented onfireNextTimer.