Eliaaazzz opened a new pull request, #39572:
URL: https://github.com/apache/beam/pull/39572

   Fixes #39446.
   
   ### The bug
   
   An unbounded source SDF that returns `ProcessContinuation.resume()` has its 
residual re-queued by `reElementResiduals` as a pending element carrying the 
*input element's* event time, which for an Impulse rooted source is 
`mtime.MinTimestamp`. That pins `minPendingTimestampLocked`, so the stage's 
watermark never advances.
   
   `updateWatermarks` returns no refreshes when the output watermark does not 
move, and `PersistBundle` marked only the **producing** stage as changed. So a 
consumer that had just been handed pending elements was never inserted into 
`em.changedStages`, `bundleReady` was never called for it, and its elements 
accumulated forever.
   
   This is worse than the issue describes: it starves plain ordinary consumers 
too, not only stateful ones, and it survives transitively through a chain of 
stages. `checkForQuiescence` cannot catch it, because the source stage stays 
schedulable, so the job live locks rather than failing fast.
   
   Reproduced at the element manager level before fixing. Pre-fix, across 5 
source bundles:
   
   ```
   round 0: src out=-inf | sink pending=1 scheduled=0
   round 4: src out=-inf | sink pending=5 scheduled=0
   ```
   
   ### The fix
   
   1. `PersistBundle` records the consumers that accepted data into 
`stageState.consumersWithNewData`, and `updateWatermarks` hands that set to the 
scheduler on the `newOut <= ss.output` path, clearing it on the advancing path 
where the normal return already lists every consumer. Routing the wake-up 
through `updateWatermarks` is what keeps a pipeline whose watermark advances on 
exactly its previous schedule.
   2. The recording is gated on `em.sawResidual`, latched the first time any 
bundle returns a residual. A pipeline that never self checkpoints never 
populates the set, so its bundle scheduling is unchanged. This matters: an 
earlier revision that recorded unconditionally changed bundle packing and broke 
`TestRunner_Pipelines/flatten_to_sideInput` at `-count=20`.
   3. `bundleReady` lets a stateful stage with no side inputs run on pending 
data alone, since `statefulStageKind.buildEventTimeBundle` already takes data 
at any watermark and gates only timers. Its `stillSchedulable` now requires 
buildable work so a key holding only a future timer cannot spin against the 
relaxed gate, and such a key no longer consumes the `OneKeyPerBundle` slot, is 
not marked in progress, and does not hold the bundle's minimum timestamp.
   
   ### What is deliberately unchanged
   
   - **The watermark value.** `BundleApplication.output_watermarks` says an 
unreported estimate means `MIN_TIMESTAMP`, and Java's `ProcessFn` holds at 
`futureOutputWatermark ?? elementTimestamp`. A pinned `MIN_TIMESTAMP` output 
watermark for a source that reports no estimate is the spec, so the TODO the 
issue points at is not where the defect is.
   - **Aggregate stages** stay on the watermark gate. A GBK genuinely needs 
window closure or a trigger.
   - **Any stage that reads a side input** stays on the watermark gate, so such 
a consumer still waits under a residual pinned source. Side input readiness is 
derived from the main watermark, and `GetSideData` filters non global windows 
by the bundle watermark, so relaxing this would let a bundle read a partial or 
empty side input. That is worse than waiting. Fixing it properly means changing 
how side inputs are materialized for every stage, which I would rather do 
separately with your input.
   
   ### Testing
   
   New `elementmanager_continuation_test.go`, all teeth checked by reverting 
each half of the fix independently:
   
   - `TestPersistBundle_ContinuationResidualConsumers`, ordinary and stateful 
consumers of a source that self checkpoints forever.
   - `TestPersistBundle_ContinuationResidualTransitive`, `src` self 
checkpoints, `mid` returns no residual of its own, `sink` two stages down.
   - `TestPersistBundle_ContinuationResidualWatermark`, pins the 
`output_watermarks` contract in both directions.
   - `TestStatefulBuildEventTimeBundle_OneKeyPerBundle`, a key headed by a 
future timer must not consume the single key slot, and must not enter `newKeys` 
or hold `minTs`.
   
   Green: `go test ./pkg/beam/runners/prism/... -count=1`, `-run 
"TestRunner_Pipelines/flatten" -count=20`, and the new tests at `-count=50`.
   
   ------------------------
   
   Thank you for your contribution! Follow this checklist to help us 
incorporate your contribution quickly and easily:
   
    - [ ] [**Choose 
reviewer(s)**](https://beam.apache.org/contribute/#make-your-change) and 
mention them in a comment (`R: @username`).
    - [ ] Mention the appropriate issue in your description (for example: 
`addresses #123`), if applicable. This will automatically add a link to the 
pull request in the issue. If you would like the issue to automatically close 
on merging the pull request, comment `fixes #<ISSUE NUMBER>` instead.
    - [ ] Update `CHANGES.md` with noteworthy changes.
    - [ ] If this contribution is large, please file an Apache [Individual 
Contributor License Agreement](https://cla.apache.org/).
   
   See the [Contributor Guide](https://beam.apache.org/contribute) for more 
tips on [how to make review process 
smoother](https://github.com/apache/beam/blob/master/CONTRIBUTING.md#make-the-reviewers-job-easier).
   
   To check the build health, please visit 
[https://github.com/apache/beam/blob/master/.test-infra/BUILD_STATUS.md](https://github.com/apache/beam/blob/master/.test-infra/BUILD_STATUS.md)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to