use of org.apache.flink.streaming.api.windowing.triggers.TriggerResult in project flink by apache.
the class TriggerTestHarness method advanceWatermark.
/**
* Advanced the watermark and processes any timers that fire because of this. The
* window and {@link TriggerResult} for each firing are returned.
*/
public Collection<Tuple2<W, TriggerResult>> advanceWatermark(long time) throws Exception {
Collection<TestInternalTimerService.Timer<Integer, W>> firedTimers = internalTimerService.advanceWatermark(time);
Collection<Tuple2<W, TriggerResult>> result = new ArrayList<>();
for (TestInternalTimerService.Timer<Integer, W> timer : firedTimers) {
TriggerResult triggerResult = invokeOnEventTime(timer);
result.add(new Tuple2<>(timer.getNamespace(), triggerResult));
}
return result;
}
use of org.apache.flink.streaming.api.windowing.triggers.TriggerResult in project flink by apache.
the class WindowOperatorContractTest method testWindowsAreMergedEagerly.
/**
* Verify that windows are merged eagerly, if possible.
*/
public void testWindowsAreMergedEagerly(final TimeDomainAdaptor timeAdaptor) throws Exception {
// in this test we only have one state window and windows are eagerly
// merged into the first window
MergingWindowAssigner<Integer, TimeWindow> mockAssigner = mockMergingAssigner();
timeAdaptor.setIsEventTime(mockAssigner);
Trigger<Integer, TimeWindow> mockTrigger = mockTrigger();
InternalWindowFunction<Iterable<Integer>, Void, Integer, TimeWindow> mockWindowFunction = mockWindowFunction();
KeyedOneInputStreamOperatorTestHarness<Integer, Integer, Void> testHarness = createWindowOperator(mockAssigner, mockTrigger, 0L, intListDescriptor, mockWindowFunction);
testHarness.open();
timeAdaptor.advanceTime(testHarness, Long.MIN_VALUE);
assertEquals(0, testHarness.extractOutputStreamRecords().size());
assertEquals(0, testHarness.numKeyedStateEntries());
doAnswer(new Answer<TriggerResult>() {
@Override
public TriggerResult answer(InvocationOnMock invocation) throws Exception {
Trigger.TriggerContext context = (Trigger.TriggerContext) invocation.getArguments()[3];
// don't intefere with cleanup timers
timeAdaptor.registerTimer(context, 0L);
context.getPartitionedState(valueStateDescriptor).update("hello");
return TriggerResult.CONTINUE;
}
}).when(mockTrigger).onElement(Matchers.<Integer>anyObject(), anyLong(), anyTimeWindow(), anyTriggerContext());
doAnswer(new Answer<TriggerResult>() {
@Override
public TriggerResult answer(InvocationOnMock invocation) throws Exception {
Trigger.OnMergeContext context = (Trigger.OnMergeContext) invocation.getArguments()[1];
// don't intefere with cleanup timers
timeAdaptor.registerTimer(context, 0L);
context.getPartitionedState(valueStateDescriptor).update("hello");
return TriggerResult.CONTINUE;
}
}).when(mockTrigger).onMerge(anyTimeWindow(), anyOnMergeContext());
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
Trigger.TriggerContext context = (Trigger.TriggerContext) invocation.getArguments()[1];
timeAdaptor.deleteTimer(context, 0L);
context.getPartitionedState(valueStateDescriptor).clear();
return null;
}
}).when(mockTrigger).clear(anyTimeWindow(), anyTriggerContext());
when(mockAssigner.assignWindows(anyInt(), anyLong(), anyAssignerContext())).thenReturn(Arrays.asList(new TimeWindow(0, 2)));
testHarness.processElement(new StreamRecord<>(0, 0L));
// window state plus trigger state plus merging window set
assertEquals(3, testHarness.numKeyedStateEntries());
// timer and GC timer
assertEquals(2, timeAdaptor.numTimers(testHarness));
when(mockAssigner.assignWindows(anyInt(), anyLong(), anyAssignerContext())).thenReturn(Arrays.asList(new TimeWindow(2, 4)));
shouldMergeWindows(mockAssigner, Lists.newArrayList(new TimeWindow(0, 2), new TimeWindow(2, 4)), Lists.newArrayList(new TimeWindow(0, 2), new TimeWindow(2, 4)), new TimeWindow(0, 4));
// don't register a timer or update state in onElement, this checks
// whether onMerge does correctly set those things
doAnswer(new Answer<TriggerResult>() {
@Override
public TriggerResult answer(InvocationOnMock invocation) throws Exception {
return TriggerResult.CONTINUE;
}
}).when(mockTrigger).onElement(Matchers.<Integer>anyObject(), anyLong(), anyTimeWindow(), anyTriggerContext());
testHarness.processElement(new StreamRecord<>(0, 0L));
verify(mockTrigger).onMerge(eq(new TimeWindow(0, 4)), anyOnMergeContext());
assertEquals(3, testHarness.numKeyedStateEntries());
assertEquals(2, timeAdaptor.numTimers(testHarness));
}
use of org.apache.flink.streaming.api.windowing.triggers.TriggerResult in project flink by apache.
the class WindowOperatorContractTest method testProcessingElementsWithinAllowedLateness.
@Test
public void testProcessingElementsWithinAllowedLateness() throws Exception {
WindowAssigner<Integer, TimeWindow> mockAssigner = mockTimeWindowAssigner();
Trigger<Integer, TimeWindow> mockTrigger = mockTrigger();
InternalWindowFunction<Iterable<Integer>, Void, Integer, TimeWindow> mockWindowFunction = mockWindowFunction();
KeyedOneInputStreamOperatorTestHarness<Integer, Integer, Void> testHarness = createWindowOperator(mockAssigner, mockTrigger, 20L, intListDescriptor, mockWindowFunction);
testHarness.open();
when(mockAssigner.assignWindows(anyInt(), anyLong(), anyAssignerContext())).thenReturn(Arrays.asList(new TimeWindow(0, 2)));
assertEquals(0, testHarness.getOutput().size());
assertEquals(0, testHarness.numKeyedStateEntries());
doAnswer(new Answer<TriggerResult>() {
@Override
public TriggerResult answer(InvocationOnMock invocation) throws Exception {
return TriggerResult.FIRE;
}
}).when(mockTrigger).onElement(Matchers.<Integer>anyObject(), anyLong(), anyTimeWindow(), anyTriggerContext());
// 20 is just at the limit, window.maxTime() is 1 and allowed lateness is 20
testHarness.processWatermark(new Watermark(20));
testHarness.processElement(new StreamRecord<>(0, 0L));
verify(mockWindowFunction, times(1)).apply(eq(0), eq(new TimeWindow(0, 2)), intIterable(0), WindowOperatorContractTest.<Void>anyCollector());
// clear is only called at cleanup time/GC time
verify(mockTrigger, never()).clear(anyTimeWindow(), anyTriggerContext());
// FIRE should not purge contents
// window contents plus trigger state
assertEquals(1, testHarness.numKeyedStateEntries());
// just the GC timer
assertEquals(1, testHarness.numEventTimeTimers());
}
use of org.apache.flink.streaming.api.windowing.triggers.TriggerResult in project flink by apache.
the class WindowTranslationTest method testMergingAssignerWithNonMergingTriggerFails.
@Test
public void testMergingAssignerWithNonMergingTriggerFails() throws Exception {
// verify that we check for trigger compatibility
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
WindowedStream<String, String, TimeWindow> windowedStream = env.fromElements("Hello", "Ciao").keyBy(new KeySelector<String, String>() {
private static final long serialVersionUID = 598309916882894293L;
@Override
public String getKey(String value) throws Exception {
return value;
}
}).window(EventTimeSessionWindows.withGap(Time.seconds(5)));
try {
windowedStream.trigger(new Trigger<String, TimeWindow>() {
private static final long serialVersionUID = 6558046711583024443L;
@Override
public TriggerResult onElement(String element, long timestamp, TimeWindow window, TriggerContext ctx) throws Exception {
return null;
}
@Override
public TriggerResult onProcessingTime(long time, TimeWindow window, TriggerContext ctx) throws Exception {
return null;
}
@Override
public TriggerResult onEventTime(long time, TimeWindow window, TriggerContext ctx) throws Exception {
return null;
}
@Override
public boolean canMerge() {
return false;
}
@Override
public void clear(TimeWindow window, TriggerContext ctx) throws Exception {
}
});
} catch (UnsupportedOperationException e) {
// use a catch to ensure that the exception is thrown by the fold
return;
}
fail("The trigger call should fail.");
}
use of org.apache.flink.streaming.api.windowing.triggers.TriggerResult in project flink by apache.
the class EvictingWindowOperator method processElement.
@Override
public void processElement(StreamRecord<IN> element) throws Exception {
Collection<W> elementWindows = windowAssigner.assignWindows(element.getValue(), element.getTimestamp(), windowAssignerContext);
@SuppressWarnings("unchecked") final K key = (K) getKeyedStateBackend().getCurrentKey();
if (windowAssigner instanceof MergingWindowAssigner) {
MergingWindowSet<W> mergingWindows = getMergingWindowSet();
for (W window : elementWindows) {
// adding the new window might result in a merge, in that case the actualWindow
// is the merged window and we work with that. If we don't merge then
// actualWindow == window
W actualWindow = mergingWindows.addWindow(window, new MergingWindowSet.MergeFunction<W>() {
@Override
public void merge(W mergeResult, Collection<W> mergedWindows, W stateWindowResult, Collection<W> mergedStateWindows) throws Exception {
context.key = key;
context.window = mergeResult;
context.onMerge(mergedWindows);
for (W m : mergedWindows) {
context.window = m;
context.clear();
deleteCleanupTimer(m);
}
// merge the merged state windows into the newly resulting state window
evictingWindowState.mergeNamespaces(stateWindowResult, mergedStateWindows);
}
});
// check if the window is already inactive
if (isWindowLate(actualWindow)) {
mergingWindows.retireWindow(actualWindow);
continue;
}
W stateWindow = mergingWindows.getStateWindow(actualWindow);
if (stateWindow == null) {
throw new IllegalStateException("Window " + window + " is not in in-flight window set.");
}
evictingWindowState.setCurrentNamespace(stateWindow);
evictingWindowState.add(element);
context.key = key;
context.window = actualWindow;
evictorContext.key = key;
evictorContext.window = actualWindow;
TriggerResult triggerResult = context.onElement(element);
if (triggerResult.isFire()) {
Iterable<StreamRecord<IN>> contents = evictingWindowState.get();
if (contents == null) {
// if we have no state, there is nothing to do
continue;
}
emitWindowContents(actualWindow, contents, evictingWindowState);
}
if (triggerResult.isPurge()) {
evictingWindowState.clear();
}
registerCleanupTimer(actualWindow);
}
mergingWindows.persist();
} else {
for (W window : elementWindows) {
// check if the window is already inactive
if (isWindowLate(window)) {
continue;
}
evictingWindowState.setCurrentNamespace(window);
evictingWindowState.add(element);
context.key = key;
context.window = window;
evictorContext.key = key;
evictorContext.window = window;
TriggerResult triggerResult = context.onElement(element);
if (triggerResult.isFire()) {
Iterable<StreamRecord<IN>> contents = evictingWindowState.get();
if (contents == null) {
// if we have no state, there is nothing to do
continue;
}
emitWindowContents(window, contents, evictingWindowState);
}
if (triggerResult.isPurge()) {
evictingWindowState.clear();
}
registerCleanupTimer(window);
}
}
}
Aggregations