@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); } }
/** * Construct a {@link TimerData} for the given parameters, where the timer ID is * deterministically generated from the {@code timestamp} and {@code domain}. */ public static TimerData of(StateNamespace namespace, Instant timestamp, TimeDomain domain) { String timerId = new StringBuilder() .append(domain.ordinal()) .append(':') .append(timestamp.getMillis()) .toString(); return of(timerId, namespace, timestamp, domain); }
@Override public TimerData decode(InputStream inStream) throws CoderException, IOException { String timerId = STRING_CODER.decode(inStream); StateNamespace namespace = StateNamespaces.fromString(STRING_CODER.decode(inStream), windowCoder); Instant timestamp = INSTANT_CODER.decode(inStream); TimeDomain domain = TimeDomain.valueOf(STRING_CODER.decode(inStream)); return TimerData.of(timerId, namespace, timestamp, domain); }
@Override public void encode(TimerData timer, OutputStream outStream) throws CoderException, IOException { STRING_CODER.encode(timer.getTimerId(), outStream); STRING_CODER.encode(timer.getNamespace().stringKey(), outStream); INSTANT_CODER.encode(timer.getTimestamp(), outStream); STRING_CODER.encode(timer.getDomain().name(), outStream); }
@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); } } }