return DoFnSignature.OnTimerMethod.create( m, timerId, requiresStableInput, windowT, extraParameters);
/** @return the {@link DoFnInvoker} for the given {@link DoFn}. */ public <InputT, OutputT> DoFnInvoker<InputT, OutputT> newByteBuddyInvoker( DoFnSignature signature, DoFn<InputT, OutputT> fn) { checkArgument( signature.fnClass().equals(fn.getClass()), "Signature is for class %s, but fn is of class %s", signature.fnClass(), fn.getClass()); try { @SuppressWarnings("unchecked") DoFnInvokerBase<InputT, OutputT, DoFn<InputT, OutputT>> invoker = (DoFnInvokerBase<InputT, OutputT, DoFn<InputT, OutputT>>) getByteBuddyInvokerConstructor(signature).newInstance(fn); for (OnTimerMethod onTimerMethod : signature.onTimerMethods().values()) { invoker.addOnTimerInvoker( onTimerMethod.id(), OnTimerInvokers.forTimer(fn, onTimerMethod.id())); } return invoker; } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) { throw new RuntimeException("Unable to bind invoker for " + fn.getClass(), e); } }
@Test public void testAllParamsOnTimer() throws Exception { final String timerId = "some-timer-id"; DoFnSignature sig = DoFnSignatures.getSignature( new DoFn<String, String>() { @TimerId(timerId) private final TimerSpec myfield1 = TimerSpecs.timer(TimeDomain.EVENT_TIME); @ProcessElement public void process(ProcessContext c) {} @OnTimer(timerId) public void onTimer( @Timestamp Instant timestamp, TimeDomain timeDomain, BoundedWindow w) {} }.getClass()); assertThat(sig.onTimerMethods().get(timerId).extraParameters().size(), equalTo(3)); assertThat( sig.onTimerMethods().get(timerId).extraParameters().get(0), instanceOf(TimestampParameter.class)); assertThat( sig.onTimerMethods().get(timerId).extraParameters().get(1), instanceOf(TimeDomainParameter.class)); assertThat( sig.onTimerMethods().get(timerId).extraParameters().get(2), instanceOf(WindowParameter.class)); }
/** * In this particular test, the super class annotated both the timer and the callback, and the * subclass overrides an abstract method. This is allowed. */ @Test public void testOnTimerDeclaredAndUsedInSuperclass() throws Exception { DoFnSignature sig = DoFnSignatures.getSignature(new DoFnOverridingAbstractCallback().getClass()); assertThat(sig.timerDeclarations().size(), equalTo(1)); assertThat(sig.onTimerMethods().size(), equalTo(1)); DoFnSignature.TimerDeclaration decl = sig.timerDeclarations().get(DoFnDeclaringTimerAndAbstractCallback.TIMER_ID); DoFnSignature.OnTimerMethod callback = sig.onTimerMethods().get(DoFnDeclaringTimerAndAbstractCallback.TIMER_ID); assertThat( decl.field(), equalTo(DoFnDeclaringTimerAndAbstractCallback.class.getDeclaredField("myTimerSpec"))); // The method we pull out is the superclass method; this is what allows validation to remain // simple. The later invokeDynamic instruction causes it to invoke the actual implementation. assertThat( callback.targetMethod(), equalTo(DoFnDeclaringTimerAndAbstractCallback.class.getDeclaredMethod("onMyTimer"))); }
@Test public void testSimpleTimerWithContext() throws Exception { DoFnSignature sig = DoFnSignatures.getSignature( new DoFn<KV<String, Integer>, Long>() { @TimerId("foo") private final TimerSpec bizzle = TimerSpecs.timer(TimeDomain.EVENT_TIME); @ProcessElement public void foo(ProcessContext context) {} @OnTimer("foo") public void onFoo(OnTimerContext c) {} }.getClass()); assertThat(sig.timerDeclarations().size(), equalTo(1)); DoFnSignature.TimerDeclaration decl = sig.timerDeclarations().get("foo"); assertThat(decl.id(), equalTo("foo")); assertThat(decl.field().getName(), equalTo("bizzle")); assertThat( sig.onTimerMethods().get("foo").extraParameters().get(0), equalTo((Parameter) Parameter.onTimerContext())); }
@Test public void testWindowParamOnTimer() throws Exception { final String timerId = "some-timer-id"; DoFnSignature sig = DoFnSignatures.getSignature( new DoFn<String, String>() { @TimerId(timerId) private final TimerSpec myfield1 = TimerSpecs.timer(TimeDomain.EVENT_TIME); @ProcessElement public void process(ProcessContext c) {} @OnTimer(timerId) public void onTimer(BoundedWindow w) {} }.getClass()); assertThat(sig.onTimerMethods().get(timerId).extraParameters().size(), equalTo(1)); assertThat( sig.onTimerMethods().get(timerId).extraParameters().get(0), instanceOf(WindowParameter.class)); }