Conversation
A FLIP-27 source that was announced as IDLE downstream stayed IDLE after it resumed, unless its next watermark strictly advanced the combined watermark. Two mechanisms compounded: * WatermarkOutputMultiplexer.updateCombinedWatermark() reported the combined idle state to the underlying output, but had no counterpart for the transition back to active; the per-output markActive() implementations only cleared the internal partial state. * WatermarkToDataOutput.emitWatermark() returned at the monotonicity guard before marking the output active, although emitting a watermark implicitly marks the stream active (see WatermarkOutput). The multiplexer now reports the idle -> active transition of the combined status to the underlying output, and a watermark on a previously idle multiplexed output triggers the combined update so that the transition is propagated eagerly instead of only on the next periodic emit. Registering a new output while the combined status is idle re-activates it right away as well, which covers the new-split special case of the same defect (FLINK-22926). WatermarkToDataOutput marks itself active before the monotonicity guard. Generated-by: DeepSeek Harness (deepseek-v4.1-flash)
Collaborator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the purpose of the change
A FLIP-27 source that has been announced as IDLE downstream stays IDLE after it resumes, unless its
next watermark strictly advances the combined watermark. Two mechanisms compound:
WatermarkOutputMultiplexer.updateCombinedWatermark()reports the combined idle state viaunderlyingOutput.markIdle(), but has no counterpart for the transition back to active; theper-output
markActive()implementations only clear internal partial state.WatermarkToDataOutput.emitWatermark()returns at the monotonicity guard(
newWatermark <= maxWatermarkSoFar) before reachingmarkActiveInternally(), although theWatermarkOutputcontract states that emitting a watermark implicitly marks the stream active.A resumed split with backlog whose watermarks are
<=the maximum flushed while all splits wereidle therefore reaches the underlying output with neither a watermark nor an ACTIVE status, and its
records are dropped as late downstream. Every sibling path re-activates eagerly
(
StatusWatermarkValve, legacyStreamSourceContexts, the tableWatermarkAssignerOperator, andDataStream V2); the FLIP-27 multiplexer path was the only one without a re-activation signal.
This also covers the new-split special case of the same defect (FLINK-22926): registering a new
output while the combined status is idle now re-activates it right away, instead of only on the
next periodic emit.
Brief change log
WatermarkOutputMultiplexerkeeps track of the idle state last reported to the underlying outputand reports the idle -> active transition via
markActive().re-activation is propagated eagerly instead of only on the next periodic emit.
registerNewOutput()updates and reports the combined status right away, so registering a newsplit while the source is idle marks the underlying output active immediately (FLINK-22926).
WatermarkToDataOutput.emitWatermark()marks the output active before the monotonicity guard.WatermarkOutputMultiplexerTestcases, 1 newWatermarkToDataOutputTestcase and2 new end-to-end
SourceOperatorEventTimeTestcases.Verifying this change
This change added tests and can be verified as follows:
mvn -pl flink-core -am -Dtest=WatermarkOutputMultiplexerTest testmvn -pl flink-runtime -am -Dtest='WatermarkToDataOutputTest,SourceOperatorEventTimeTest' testwith it (red/green verification by reverting the three production files, and separately by
reverting the
registerNewOutput()update).flink-core-api,flink-coreandflink-runtime(20 classes, 137 tests) passes on a clean build.SourceOperatorEventTimeTest#testResumingSplitWithoutAdvancingWatermarkEmitsActivereproduces thescenario from the ticket: all splits go idle, the combined watermark is flushed to the maximum, a
split resumes with backlog whose watermarks do not advance the combined watermark, and the edge
must emit ACTIVE.
SourceOperatorEventTimeTest#testRegisteringNewSplitWhileIdleEmitsActivecovers FLINK-22926. Itdeliberately does not advance the processing time service, because a periodic watermark emit
would re-activate the output lazily as well and would mask the immediate re-activation under test.
Notes for reviewers:
TimestampsAndWatermarks.WatermarkUpdateListenerimplementation isSourceOperator.emitWatermark()now callsmarkActiveInternally()beforeupdateCurrentEffectiveWatermark()for advancing watermarks (the downstream event order ACTIVE -> watermark is unchanged).
updateIdle()only writes a field thatcheckWatermarkAlignment()does not read, so the swappedlistener callback order has no observable effect.
unregisterOutput()still does not update the combined status, so removing the last active outputwhile others are idle is only reflected on the next periodic emit. This is a pre-existing,
bounded-delay issue of the same family and is deliberately left out of this change.
tasks; this PR fixes the root cause and does not touch those files. It also covers the new-split
case described in FLINK-22926, which can be closed together with this change.
Does this pull request potentially affect one of the following parts:
WatermarkOutputMultiplexerandWatermarkToDataOutputare@Internal)ImmediateOutput.emitWatermark()gains one field read and a branch; the combined update (whichiterates all splits) still only runs on a watermark advance, an idle -> active transition, or a
registration
Documentation
Generated-by: DeepSeek Harness (deepseek-v4.1-flash)