public static <W extends BoundedWindow, AccumT, OutputT> TriggerTester<Integer, OutputT, W> combining( WindowFn<?, W> windowFn, Trigger<W> trigger, AccumulationMode mode, KeyedCombineFn<String, Integer, AccumT, OutputT> combineFn, Coder<OutputT> outputCoder, Duration allowedDataLateness) throws Exception { WindowingStrategy<?, W> strategy = WindowingStrategy.of(windowFn) .withTrigger(trigger) .withMode(mode) .withAllowedLateness(allowedDataLateness); CoderRegistry registry = new CoderRegistry(); registry.registerStandardCoders(); AppliedCombineFn<String, Integer, AccumT, OutputT> fn = AppliedCombineFn.<String, Integer, AccumT, OutputT>withInputCoder( combineFn, registry, KvCoder.of(StringUtf8Coder.of(), VarIntCoder.of())); return new TriggerTester<Integer, OutputT, W>( strategy, SystemReduceFn.<String, Integer, AccumT, OutputT, W>combining(StringUtf8Coder.of(), fn) .create(KEY), outputCoder); }
public static boolean isSupported(WindowingStrategy<?, ?> strategy) { // TODO: Add support for other triggers. if (!(strategy.getTrigger().getSpec() instanceof DefaultTrigger)) { return false; } // Right now, we support ACCUMULATING_FIRED_PANES because it is the same as // DISCARDING_FIRED_PANES. In Batch mode there is no late data so the default // trigger (after watermark) will only fire once. if (!strategy.getMode().equals(AccumulationMode.DISCARDING_FIRED_PANES) && !strategy.getMode().equals(AccumulationMode.ACCUMULATING_FIRED_PANES)) { return false; } return true; }
private TriggerTester( WindowingStrategy<?, W> wildcardStrategy, ReduceFn<String, InputT, OutputT, W> reduceFn, Coder<OutputT> outputCoder) throws Exception { @SuppressWarnings("unchecked") WindowingStrategy<Object, W> objectStrategy = (WindowingStrategy<Object, W>) wildcardStrategy; this.windowFn = objectStrategy.getWindowFn(); this.stubContexts = new StubContexts(); this.outputCoder = outputCoder; executableTrigger = wildcardStrategy.getTrigger(); this.runner = new ReduceFnRunner<>( KEY, objectStrategy, timerInternals, stubContexts, droppedDueToClosedWindow, droppedDueToLateness, reduceFn); }
public static <W extends BoundedWindow> TriggerTester<Integer, Iterable<Integer>, W> nonCombining( WindowFn<?, W> windowFn, Trigger<W> trigger, AccumulationMode mode, Duration allowedDataLateness) throws Exception { WindowingStrategy<?, W> strategy = WindowingStrategy.of(windowFn) .withTrigger(trigger) .withMode(mode) .withAllowedLateness(allowedDataLateness); return nonCombining(strategy); }
protected <T> WindowedValue<T> makeWindowedValue( T output, Instant timestamp, Collection<? extends BoundedWindow> windows, PaneInfo pane) { final Instant inputTimestamp = timestamp; final WindowFn windowFn = windowingStrategy.getWindowFn(); if (timestamp == null) { timestamp = BoundedWindow.TIMESTAMP_MIN_VALUE; } if (windows == null) { try { windows = windowFn.assignWindows( windowFn.new AssignContext() { @Override public Object element() { throw new UnsupportedOperationException( "WindowFn attempted to access input element when none was available"); // TODO: 12/16/15 aljoscha's comment in slack } @Override public Instant timestamp() { if (inputTimestamp == null) { throw new UnsupportedOperationException( "WindowFn attempted to access input timestamp when none was available"); } return inputTimestamp; } @Override public Collection<? extends BoundedWindow> windows() { throw new UnsupportedOperationException( "WindowFn attempted to access input windows when none were available"); } }); } catch (Exception e) { Throwables.propagateIfInstanceOf(e, UserCodeException.class); throw new UserCodeException(e); } } return WindowedValue.of(output, timestamp, windows, pane); }