/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.samza.operators.windows.internal; import org.apache.samza.annotation.InterfaceStability; import org.apache.samza.operators.functions.MapFunction; import org.apache.samza.operators.functions.SupplierFunction; import org.apache.samza.operators.functions.FoldLeftFunction; import org.apache.samza.operators.triggers.Trigger; import org.apache.samza.operators.windows.AccumulationMode; import org.apache.samza.operators.windows.Window; import org.apache.samza.serializers.Serde; /** * Internal representation of a {@link Window}. This specifies default, early and late triggers for the {@link Window} * and whether to accumulate or discard previously emitted panes. * * Note: This class is meant to be used internally by Samza, and is not to be instantiated by programmers. * * @param <M> the type of input message * @param <WK> the type of key for the window * @param <WV> the type of aggregated value in the window output */ @InterfaceStability.Unstable public final class WindowInternal<M, WK, WV> implements Window<M, WK, WV> { private final Trigger<M> defaultTrigger; /** * The supplier of initial value to be used for windowed aggregations */ private final SupplierFunction<WV> initializer; /* * The function that is applied each time a {@link MessageEnvelope} is added to this window. */ private final FoldLeftFunction<M, WV> foldLeftFunction; /* * The function that extracts the key from a {@link MessageEnvelope} */ private final MapFunction<M, WK> keyExtractor; /* * The function that extracts the event time from a {@link MessageEnvelope} */ private final MapFunction<M, Long> eventTimeExtractor; /** * The type of this window. Tumbling and Session windows are supported for now. */ private final WindowType windowType; private Trigger<M> earlyTrigger; private Trigger<M> lateTrigger; private AccumulationMode mode; /** * The following {@link Serde}s are serialized by the ExecutionPlanner when generating the store configs, and deserialized * once during startup in SamzaContainer. They don't need to be deserialized here on a per-task basis */ private transient final Serde<WK> keySerde; private transient final Serde<WV> windowValSerde; private transient final Serde<M> msgSerde; public WindowInternal(Trigger<M> defaultTrigger, SupplierFunction<WV> initializer, FoldLeftFunction<M, WV> foldLeftFunction, MapFunction<M, WK> keyExtractor, MapFunction<M, Long> eventTimeExtractor, WindowType windowType, Serde<WK> keySerde, Serde<WV> windowValueSerde, Serde<M> msgSerde) { this.defaultTrigger = defaultTrigger; this.initializer = initializer; this.foldLeftFunction = foldLeftFunction; this.eventTimeExtractor = eventTimeExtractor; this.keyExtractor = keyExtractor; this.windowType = windowType; this.keySerde = keySerde; this.windowValSerde = windowValueSerde; this.msgSerde = msgSerde; if (defaultTrigger == null) { throw new IllegalArgumentException("A window must not have a null default trigger"); } if (msgSerde == null && windowValueSerde == null) { throw new IllegalArgumentException("A window must not have a null msg serde and a null windowValue serde"); } if (foldLeftFunction != null && windowValSerde == null) { throw new IllegalArgumentException("A window with a FoldLeftFunction must have a windowValue serde"); } if (foldLeftFunction != null && initializer == null) { throw new IllegalArgumentException("A window with a FoldLeftFunction must have an initializer"); } if (foldLeftFunction == null && initializer != null) { throw new IllegalArgumentException("A window without a provided FoldLeftFunction must not have an initializer"); } } public Trigger<M> getDefaultTrigger() { return defaultTrigger; } public Trigger<M> getEarlyTrigger() { return earlyTrigger; } public Trigger<M> getLateTrigger() { return lateTrigger; } public SupplierFunction<WV> getInitializer() { return initializer; } public FoldLeftFunction<M, WV> getFoldLeftFunction() { return foldLeftFunction; } public MapFunction<M, WK> getKeyExtractor() { return keyExtractor; } public MapFunction<M, Long> getEventTimeExtractor() { return eventTimeExtractor; } public WindowType getWindowType() { return windowType; } public AccumulationMode getAccumulationMode() { return mode; } public Serde<WK> getKeySerde() { return keySerde; } public Serde<WV> getWindowValSerde() { return windowValSerde; } public Serde<M> getMsgSerde() { return msgSerde; } public AccumulationMode getMode() { return mode; } @Override public Window<M, WK, WV> setEarlyTrigger(Trigger<M> trigger) { this.earlyTrigger = trigger; return this; } @Override public Window<M, WK, WV> setLateTrigger(Trigger<M> trigger) { this.lateTrigger = trigger; return this; } @Override public Window<M, WK, WV> setAccumulationMode(AccumulationMode mode) { this.mode = mode; return this; } }