-
Notifications
You must be signed in to change notification settings - Fork 13.9k
[FLINK-39073][runtime] Defer alignment check for idle splits #27638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+107
−12
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,6 +73,8 @@ Licensed to the Apache Software Foundation (ASF) under one | |
| import static org.apache.flink.configuration.PipelineOptions.WATERMARK_ALIGNMENT_BUFFER_SIZE; | ||
| import static org.apache.flink.runtime.executiongraph.ExecutionGraphTestUtils.createExecutionAttemptId; | ||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertNotEquals; | ||
|
|
||
| /** Unit test for split alignment in {@link SourceOperator}. */ | ||
| class SourceOperatorSplitWatermarkAlignmentTest { | ||
|
|
@@ -501,6 +503,72 @@ void testStateReportingForSingleSplitWatermarkAlignmentAndIdleness() throws Exce | |
| assertThat(operator.getSplitMetricGroup(split0.splitId()).isActive()).isTrue(); | ||
| } | ||
|
|
||
| @Test | ||
| void testAlignmentCheckIsDeferredForIdleSplits() throws Exception { | ||
| final long idleTimeout = 100; | ||
| final MockSourceReader sourceReader = | ||
| new MockSourceReader(WaitingForSplits.DO_NOT_WAIT_FOR_SPLITS, true, true); | ||
| final TestProcessingTimeService processingTimeService = new TestProcessingTimeService(); | ||
| // Split states math assumes non-negative time | ||
| processingTimeService.setCurrentTime(0); | ||
| final SourceOperator<Integer, MockSourceSplit> operator = | ||
| createAndOpenSourceOperatorWithIdleness( | ||
| sourceReader, processingTimeService, idleTimeout); | ||
|
|
||
| final MockSourceSplit split0 = new MockSourceSplit(0, 0, 10); | ||
| final int allowedWatermark4 = 4; | ||
| final int allowedWatermark7 = 7; | ||
| split0.addRecord(5); | ||
| split0.addRecord(6); | ||
| split0.addRecord(7); | ||
| split0.addRecord(8); | ||
| operator.handleOperatorEvent( | ||
| new AddSplitEvent<>(Arrays.asList(split0), new MockSourceSplitSerializer())); | ||
| final CollectingDataOutput<Integer> actualOutput = new CollectingDataOutput<>(); | ||
|
|
||
| // Emit enough record to fill the sampler buffer | ||
| operator.emitNext(actualOutput); | ||
| operator.emitNext(actualOutput); | ||
| operator.emitNext(actualOutput); | ||
| sampleAllWatermarks(processingTimeService); | ||
|
|
||
| // Transition the split to idle state: | ||
| for (int i = 0; i < 10; i++) { | ||
| processingTimeService.advance(idleTimeout); | ||
| } | ||
| assertThat(operator.getSplitMetricGroup(split0.splitId()).isIdle()).isTrue(); | ||
|
|
||
| // Alignment check fires but doesn't pause the idle split | ||
| operator.handleOperatorEvent(new WatermarkAlignmentEvent(allowedWatermark4)); | ||
| assertThat(operator.getSplitMetricGroup(split0.splitId()).isIdle()).isTrue(); | ||
|
Comment on lines
+541
to
+543
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we assert that the split hasn't been paused?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
|
||
| // While the split is idle, we advance the allowed watermark to keep the source active | ||
| operator.handleOperatorEvent(new WatermarkAlignmentEvent(allowedWatermark7)); | ||
| sampleAllWatermarks(processingTimeService); | ||
| // The split is still idle: | ||
| assertThat(operator.getSplitMetricGroup(split0.splitId()).isIdle()).isTrue(); | ||
|
|
||
| // updating timers values manually (in reality this is done by ViewUpdater) | ||
| operator.getSplitMetricGroup(split0.splitId()).updateTimers(); | ||
| // Ensure the idle timer ticked, but not pause timer | ||
| assertNotEquals( | ||
| 0L, operator.getSplitMetricGroup(split0.splitId()).getAccumulatedIdleTime()); | ||
| assertEquals(0L, operator.getSplitMetricGroup(split0.splitId()).getAccumulatedPausedTime()); | ||
|
|
||
| // The split emits a record to break out of idleness | ||
| operator.emitNext(actualOutput); | ||
| sampleAllWatermarks(processingTimeService); | ||
|
|
||
| // The split is marked not idle, then immediately paused by the deferred alignment check | ||
| assertThat(operator.getSplitMetricGroup(split0.splitId()).isPaused()).isTrue(); | ||
|
|
||
| // Make pause timer tick | ||
| processingTimeService.advance(10); | ||
| operator.getSplitMetricGroup(split0.splitId()).updateTimers(); | ||
| assertNotEquals( | ||
| 0L, operator.getSplitMetricGroup(split0.splitId()).getAccumulatedPausedTime()); | ||
| } | ||
|
|
||
| private void sampleAllWatermarks(TestProcessingTimeService timeService) throws Exception { | ||
| sampleWatermarks(timeService, WATERMARK_ALIGNMENT_BUFFER_SIZE.defaultValue()); | ||
| } | ||
|
|
||
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.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the method name is strange - I was expecting it to start with a verb like the other methods. Maybe `updateCurrentSplitPausedWatermark
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method checks if the split watermark is too advanced and if yes calls
pauseOrResumeSplitfor it, unless already paused.I am not aware of a "paused watermark" concept, but open to other suggestions on how to name this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the
maybePauseSplitdecsribes pretty well what's happening. Also there are plenty of other cases with similar naming convention (method namedmaybeACTION).Re
updateCurrentSplitPausedWatermark:updateCurrentPausedSplitWatermark, but in this case "Paused watermark" is still confusing as pointed by @Efrat19 . Even more correct would have beenupdateCurrentlyPausedSplit...updateCurrentlyPausedSplitdoesn't capture that currently paused split split might not be updatedupdateCurrentlyPausedSplitis basically as synonym ofpauseSplitsSo:
maybePauseSplitandmaybeUpdateCurrentlyPausedSplitare both technically correctmaybePauseSplitsimo sounds better, so I would keep it as is.