Repository navigation
Conversation
|
/gemini review |
There was a problem hiding this comment.
📋 Review Summary
This PR resolves a race condition in portable Spark Streaming where subsequent micro-batches could execute before WatermarkAdvancingStreamingListener finished advancing watermarks for the prior batch, causing downstream stages in multi-GBK topologies to observe inconsistent watermarks. It also properly resets GlobalWatermarkHolder and MetricsAccumulator state in SparkPipelineRunner between sequential runs and synchronizes watermark state access in GlobalWatermarkHolder.
🔍 General Feedback
- Synchronizing
SingleEmitInputDStream.compute(Time)againstGlobalWatermarkHolder.getLastWatermarkedBatchTime()(matchingTestDStream's pattern) and guarding onGlobalWatermarkHolder.hasWatermarks()cleanly prevents out-of-order watermark reads across stages without hanging non-watermarked streams or checkpoint recovery tests. - Synchronizing
add,addAll,hasWatermarks, andgetinGlobalWatermarkHolderand resettingwatermarkCacheinclear()closes thread-safety and state-leakage gaps when multiple streaming pipelines run in the same JVM.
💡 Tip: Comment /gemini review on this pull request to trigger a new Gemini code review.
…ing and clear GlobalWatermarkHolder after streaming runs
|
/gemini review |
There was a problem hiding this comment.
📋 Review Summary
This PR resolves a race condition in the Spark Runner DStream streaming mode where SingleEmitInputDStream could generate subsequent micro-batch RDDs before WatermarkAdvancingStreamingListener finished advancing watermarks for the completed batch. The changes cleanly synchronize SingleEmitInputDStream batch generation with GlobalWatermarkHolder in portable streaming pipelines, add missing thread synchronization to GlobalWatermarkHolder, and ensure static watermark and metrics state is cleared between pipeline runs.
🔍 General Feedback
- Gating watermark synchronization in
SingleEmitInputDStreambehindforceWatermarkSyncand guarding against repeatedcomputecalls for the samevalidTime(validTime.milliseconds() > lastValidTimeMs) safely aligns portableImpulse/Flattenstreams withTestDStreamwithout affecting existing callers. - Synchronizing
GlobalWatermarkHolderaccessors (add,addAll,hasWatermarks,get) on the class monitor and resettingwatermarkCacheinclear()eliminates cross-thread visibility and state leakage issues across sequential runs.
💡 Tip: Comment /gemini review on this pull request to trigger a new Gemini code review.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #41286 +/- ##
=========================================
Coverage 59.26% 59.26%
Complexity 4925 4925
=========================================
Files 1462 1462
Lines 186313 186313
Branches 3669 3669
=========================================
Hits 110417 110417
Misses 72540 72540
Partials 3356 3356 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Note: this PR was auto-generated by tooling. Before moving it out of draft, the author has done a full review of the PR, specifically evaluating it on the following criteria:
Full details of the methodology of generation and review can be found here - https://docs.google.com/document/d/14lj7ECVov4T4EdwmIzNlWrRGE3lLDMOwX5xUMGzaLoc/edit?usp=sharing
If you have concerns with the PR or with the underlying methodology used to generate this, please comment below - they will be addressed by the author not the tooling :)
Summary
Fixes a watermark synchronization race in Spark Runner DStream streaming pipelines (
PostCommit Java PVR Spark4 Streaming, e.g. https://github.com/apache/beam/actions/runs/43374186705/job/131716702201) whereCombineTest$BasicTests.testBinaryCombinePerKeyInstanceMethodReferencefailed with:Production Impact
Impacts real Spark Runner streaming pipelines (both Portable DStream streaming and Classic streaming pipelines using
Flatten/ImpulseviaSingleEmitInputDStream).GroupByKey/Combine.perKeytopologies where a micro-batch takes longer thanbatchIntervalMillis(default1000ms), or running multiple pipelines sequentially in the same JVM viaSparkPipelineRunner.TestDStream(waitForLastBatch) andWatermarkSyncedDStream(awaitWatermarkSyncWith),SingleEmitInputDStream.compute(Time)did not wait for the previous micro-batch's watermark advancement (GlobalWatermarkHolder.getLastWatermarkedBatchTime()) before generating the next micro-batch's RDD. When Batch 1 takes longer thanbatchIntervalMillis(e.g., while initializing the SDK harness), Spark Streaming'sJobGeneratorqueues Batch 2 while Batch 1 is still executing. As soon as Batch 1's Spark job finishes,JobScheduler.jobExecutorstarts executing Batch 2 concurrently withWatermarkAdvancingStreamingListener.onBatchCompleted(Batch 1)running on Spark's asynchronousLiveListenerBusthread.SparkGroupAlsoByWindowViaWindowSetfetchesGlobalWatermarkHolder.get(...)lazily inside each stage on the executor, an upstreamGroupByKeystage (Combine.perKey) in Batch 2 can readGlobalWatermarkHolder.get(...)beforeadvance()completes (seeingTIMESTAMP_MIN_VALUEand not firing its buffered elements), while a downstreamGroupByKeystage (PAssert) in the same Batch 2 readsGlobalWatermarkHolder.get(...)milliseconds later afteradvance()completes (seeingTIMESTAMP_MAX_VALUEand firing premature timers before upstream results arrive).SparkPipelineRunner.rundid not callGlobalWatermarkHolder.clear()orMetricsAccumulator.clear()(unlikeTestSparkRunner.run), leaving static watermark and metrics state dirty across sequential pipeline runs in the same JVM, andGlobalWatermarkHolder.add/getwere not synchronized withadvance.SingleEmitInputDStream.compute(Time)now waits forGlobalWatermarkHolder.getLastWatermarkedBatchTime() >= lastValidTimeMswhen watermarks are registered (matchingTestDStream), ensuring BatchN+1is not generated until BatchN's watermark update has completed.GlobalWatermarkHolder.add,addAll,get, andhasWatermarksonGlobalWatermarkHolder.class, and resetswatermarkCacheinclear().MetricsAccumulatorandGlobalWatermarkHolderinSparkPipelineRunner.runbefore starting a pipeline.Verification
beam_PostCommit_Java_PVR_Spark4_Streaming.ymlworkflow run on branch:43388934435