Skip to content

Commit 9541b4c

Browse files
curcurdawidwys
authored andcommitted
[FLINK-21469][runtime] Implement advanceToEndOfEventTime for MultipleInputStreamTask
For stop with savepoint, StreamTask#advanceToEndOfEventTime() is called (in source tasks) to advance to the max watermark. This PR implments advanceToEndOfEventTime for MultipleInputStreamTask chained sources.
1 parent 531158f commit 9541b4c

3 files changed

Lines changed: 58 additions & 28 deletions

File tree

flink-streaming-java/src/main/java/org/apache/flink/streaming/runtime/tasks/MultipleInputStreamTask.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@
3030
import org.apache.flink.streaming.api.graph.StreamConfig.InputConfig;
3131
import org.apache.flink.streaming.api.graph.StreamEdge;
3232
import org.apache.flink.streaming.api.operators.MultipleInputStreamOperator;
33+
import org.apache.flink.streaming.api.operators.Output;
34+
import org.apache.flink.streaming.api.watermark.Watermark;
3335
import org.apache.flink.streaming.runtime.io.CheckpointBarrierHandler;
3436
import org.apache.flink.streaming.runtime.io.CheckpointedInputGate;
3537
import org.apache.flink.streaming.runtime.io.InputProcessorUtil;
3638
import org.apache.flink.streaming.runtime.io.StreamMultipleInputProcessorFactory;
3739
import org.apache.flink.streaming.runtime.io.StreamTaskSourceInput;
3840
import org.apache.flink.streaming.runtime.metrics.MinWatermarkGauge;
3941
import org.apache.flink.streaming.runtime.metrics.WatermarkGauge;
42+
import org.apache.flink.streaming.runtime.streamrecord.StreamRecord;
4043

4144
import javax.annotation.Nullable;
4245

@@ -256,4 +259,11 @@ public void abortCheckpointOnBarrier(long checkpointId, Throwable cause) throws
256259
}
257260
super.abortCheckpointOnBarrier(checkpointId, cause);
258261
}
262+
263+
@Override
264+
protected void advanceToEndOfEventTime() throws Exception {
265+
for (Output<StreamRecord<?>> sourceOutput : operatorChain.getChainedSourceOutputs()) {
266+
sourceOutput.emitWatermark(Watermark.MAX_WATERMARK);
267+
}
268+
}
259269
}

flink-streaming-java/src/main/java/org/apache/flink/streaming/runtime/tasks/OperatorChain.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,12 @@ public Output<StreamRecord<?>> getChainedSourceOutput(SourceInputConfig sourceIn
475475
return chainedSources.get(sourceInput).getSourceOutput();
476476
}
477477

478+
public List<Output<StreamRecord<?>>> getChainedSourceOutputs() {
479+
return chainedSources.values().stream()
480+
.map(ChainedSource::getSourceOutput)
481+
.collect(Collectors.toList());
482+
}
483+
478484
public StreamTaskSourceInput<?> getSourceTaskInput(SourceInputConfig sourceInput) {
479485
checkArgument(
480486
chainedSources.containsKey(sourceInput),

flink-streaming-java/src/test/java/org/apache/flink/streaming/runtime/tasks/MultipleInputStreamTaskTest.java

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
import static org.hamcrest.MatcherAssert.assertThat;
9191
import static org.hamcrest.Matchers.contains;
9292
import static org.hamcrest.Matchers.containsInAnyOrder;
93+
import static org.hamcrest.Matchers.not;
9394
import static org.junit.Assert.assertEquals;
9495
import static org.junit.Assert.assertTrue;
9596

@@ -510,20 +511,7 @@ public void testInputFairness() throws Exception {
510511
@Test
511512
public void testWatermark() throws Exception {
512513
try (StreamTaskMailboxTestHarness<String> testHarness =
513-
new StreamTaskMailboxTestHarnessBuilder<>(
514-
MultipleInputStreamTask::new, BasicTypeInfo.STRING_TYPE_INFO)
515-
.modifyExecutionConfig(config -> config.enableObjectReuse())
516-
.addInput(BasicTypeInfo.STRING_TYPE_INFO, 2)
517-
.addSourceInput(
518-
new SourceOperatorFactory<>(
519-
new MockSource(
520-
Boundedness.CONTINUOUS_UNBOUNDED, 2, true, false),
521-
WatermarkStrategy.forGenerator(
522-
ctx -> new RecordToWatermarkGenerator())))
523-
.addInput(BasicTypeInfo.DOUBLE_TYPE_INFO, 2)
524-
.setupOutputForSingletonOperatorChain(
525-
new MapToStringMultipleInputOperatorFactory(3))
526-
.build()) {
514+
buildWatermarkTestHarness(2, false)) {
527515
ArrayDeque<Object> expectedOutput = new ArrayDeque<>();
528516

529517
int initialTime = 0;
@@ -600,20 +588,7 @@ public void testWatermark() throws Exception {
600588
@Test
601589
public void testWatermarkAndStreamStatusForwarding() throws Exception {
602590
try (StreamTaskMailboxTestHarness<String> testHarness =
603-
new StreamTaskMailboxTestHarnessBuilder<>(
604-
MultipleInputStreamTask::new, BasicTypeInfo.STRING_TYPE_INFO)
605-
.modifyExecutionConfig(config -> config.enableObjectReuse())
606-
.addInput(BasicTypeInfo.STRING_TYPE_INFO, 2)
607-
.addSourceInput(
608-
new SourceOperatorFactory<>(
609-
new MockSource(
610-
Boundedness.CONTINUOUS_UNBOUNDED, 2, true, true),
611-
WatermarkStrategy.forGenerator(
612-
ctx -> new RecordToWatermarkGenerator())))
613-
.addInput(BasicTypeInfo.DOUBLE_TYPE_INFO, 2)
614-
.setupOutputForSingletonOperatorChain(
615-
new MapToStringMultipleInputOperatorFactory(3))
616-
.build()) {
591+
buildWatermarkTestHarness(2, true)) {
617592
ArrayDeque<Object> expectedOutput = new ArrayDeque<>();
618593

619594
int initialTime = 0;
@@ -676,6 +651,24 @@ public void testWatermarkAndStreamStatusForwarding() throws Exception {
676651
}
677652
}
678653

654+
@Test
655+
public void testAdvanceToEndOfEventTime() throws Exception {
656+
try (StreamTaskMailboxTestHarness<String> testHarness =
657+
buildWatermarkTestHarness(2, false)) {
658+
testHarness.processElement(Watermark.MAX_WATERMARK, 0, 0);
659+
testHarness.processElement(Watermark.MAX_WATERMARK, 0, 1);
660+
661+
testHarness.getStreamTask().advanceToEndOfEventTime();
662+
663+
testHarness.processElement(Watermark.MAX_WATERMARK, 1, 0);
664+
665+
assertThat(testHarness.getOutput(), not(contains(Watermark.MAX_WATERMARK)));
666+
667+
testHarness.processElement(Watermark.MAX_WATERMARK, 1, 1);
668+
assertThat(testHarness.getOutput(), contains(Watermark.MAX_WATERMARK));
669+
}
670+
}
671+
679672
@Test
680673
@SuppressWarnings("unchecked")
681674
public void testWatermarkMetrics() throws Exception {
@@ -1026,6 +1019,27 @@ static void addSourceRecords(
10261019
.dispatchOperatorEvent(sourceOperatorID, new SerializedValue<>(addSplitEvent));
10271020
}
10281021

1022+
private static StreamTaskMailboxTestHarness<String> buildWatermarkTestHarness(
1023+
int inputChannels, boolean readerMarkIdleOnNoSplits) throws Exception {
1024+
return new StreamTaskMailboxTestHarnessBuilder<>(
1025+
MultipleInputStreamTask::new, BasicTypeInfo.STRING_TYPE_INFO)
1026+
.modifyExecutionConfig(config -> config.enableObjectReuse())
1027+
.addInput(BasicTypeInfo.STRING_TYPE_INFO, inputChannels)
1028+
.addSourceInput(
1029+
new SourceOperatorFactory<>(
1030+
new MockSource(
1031+
Boundedness.CONTINUOUS_UNBOUNDED,
1032+
2,
1033+
true,
1034+
readerMarkIdleOnNoSplits),
1035+
WatermarkStrategy.forGenerator(
1036+
ctx -> new RecordToWatermarkGenerator())))
1037+
.addInput(BasicTypeInfo.DOUBLE_TYPE_INFO, inputChannels)
1038+
.setupOutputForSingletonOperatorChain(
1039+
new MapToStringMultipleInputOperatorFactory(3))
1040+
.build();
1041+
}
1042+
10291043
private static OperatorID getSourceOperatorID(
10301044
StreamTaskMailboxTestHarness<String> testHarness, int sourceId) {
10311045
StreamConfig.InputConfig[] inputs =

0 commit comments

Comments
 (0)