@Override public boolean isForWindow( String timerId, BoundedWindow window, Instant timestamp, TimeDomain timeDomain) { boolean isEventTimer = timeDomain.equals(TimeDomain.EVENT_TIME); Instant gcTime = LateDataUtils.garbageCollectionTime(window, windowingStrategy); gcTime = gcTime.plus(GC_DELAY_MS); return isEventTimer && GC_TIMER_ID.equals(timerId) && gcTime.equals(timestamp); } }
@OnTimer(timerId) public void onTimer(TimeDomain timeDomain, OutputReceiver<Integer> r) { if (timeDomain.equals(TimeDomain.EVENT_TIME)) { r.output(42); } } };
@OnTimer(TIMER_ID) public void onTimer(TimeDomain timeDomain, OutputReceiver<Integer> r) { if (timeDomain.equals(TimeDomain.EVENT_TIME)) { r.output(42); } } };
@OnTimer(timerId) public void onTimer(TimeDomain timeDomain, OutputReceiver<Integer> r) { if (timeDomain.equals(TimeDomain.PROCESSING_TIME)) { r.output(42); } } };
@Override public void fireTimer(InternalTimer<?, TimerInternals.TimerData> timer) { if (timer.getNamespace().getDomain().equals(TimeDomain.EVENT_TIME)) { // ignore this, it can only be a state cleanup timers from StatefulDoFnRunner and ProcessFn // does its own state cleanup and should never set event-time timers. return; } doFnRunner.processElement( WindowedValue.valueInGlobalWindow( KeyedWorkItems.timersWorkItem( (byte[]) keyedStateInternals.getKey(), Collections.singletonList(timer.getNamespace())))); }
@Override public void fireTimer(InternalTimer<?, TimerInternals.TimerData> timer) { timerInternals.cleanupPendingTimer(timer.getNamespace()); if (timer.getNamespace().getDomain().equals(TimeDomain.EVENT_TIME)) { // ignore this, it can only be a state cleanup timers from StatefulDoFnRunner and ProcessFn // does its own state cleanup and should never set event-time timers. return; } doFnRunner.processElement( WindowedValue.valueInGlobalWindow( KeyedWorkItems.timersWorkItem( (byte[]) keyedStateInternals.getKey(), Collections.singletonList(timer.getNamespace())))); }
@Override public void onTimer( String timerId, BoundedWindow window, Instant timestamp, TimeDomain timeDomain) { if (cleanupTimer.isForWindow(timerId, window, timestamp, timeDomain)) { stateCleaner.clearForWindow(window); // There should invoke the onWindowExpiration of DoFn } else { // An event-time timer can never be late because we don't allow setting timers after GC time. // Ot can happen that a processing-time time fires for a late window, we need to ignore // this. if (!timeDomain.equals(TimeDomain.EVENT_TIME) && isLate(window)) { // don't increment the dropped counter, only do that for elements WindowTracing.debug( "StatefulDoFnRunner.onTimer: Ignoring processing-time timer at {}; window:{} " + "since window is too far behind inputWatermark:{}", timestamp, window, cleanupTimer.currentInputWatermarkTime()); } else { doFnRunner.onTimer(timerId, window, timestamp, timeDomain); } } }
/** @deprecated use {@link #setTimer(StateNamespace, String, Instant, TimeDomain)}. */ @Deprecated @Override public void setTimer(TimerData timerData) { WindowTracing.trace("{}.setTimer: {}", getClass().getSimpleName(), timerData); @Nullable TimerData existing = existingTimers.get(timerData.getNamespace(), timerData.getTimerId()); if (existing == null) { existingTimers.put(timerData.getNamespace(), timerData.getTimerId(), timerData); timersForDomain(timerData.getDomain()).add(timerData); } else { checkArgument( timerData.getDomain().equals(existing.getDomain()), "Attempt to set %s for time domain %s, but it is already set for time domain %s", timerData.getTimerId(), timerData.getDomain(), existing.getDomain()); if (!timerData.getTimestamp().equals(existing.getTimestamp())) { NavigableSet<TimerData> timers = timersForDomain(timerData.getDomain()); timers.remove(existing); timers.add(timerData); existingTimers.put(timerData.getNamespace(), timerData.getTimerId(), timerData); } } }