All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fluxtion.runtime.dataflow.groupby.GroupByTimedSlidingWindow Maven / Gradle / Ivy

package com.fluxtion.runtime.dataflow.groupby;

import com.fluxtion.runtime.annotations.OnParentUpdate;
import com.fluxtion.runtime.annotations.OnTrigger;
import com.fluxtion.runtime.annotations.builder.AssignToField;
import com.fluxtion.runtime.dataflow.FlowFunction;
import com.fluxtion.runtime.dataflow.TriggeredFlowFunction;
import com.fluxtion.runtime.dataflow.aggregate.AggregateFlowFunction;
import com.fluxtion.runtime.dataflow.aggregate.function.BucketedSlidingWindow;
import com.fluxtion.runtime.dataflow.function.AbstractFlowFunction;
import com.fluxtion.runtime.partition.LambdaReflection.SerializableFunction;
import com.fluxtion.runtime.partition.LambdaReflection.SerializableSupplier;
import com.fluxtion.runtime.time.FixedRateTrigger;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;


/**
 * @param  Input type
 * @param  Output of aggregate function
 * @param  Key type from input T
 * @param  Value type from input T, input to aggregate function
 * @param  {@link FlowFunction} input type
 * @param 
 */
public class GroupByTimedSlidingWindow, F extends AggregateFlowFunction>
        extends AbstractFlowFunction, S>
        implements TriggeredFlowFunction> {

    private final SerializableSupplier windowFunctionSupplier;
    private final SerializableFunction keyFunction;
    private final SerializableFunction valueFunction;
    private final int bucketSizeMillis;
    private final int bucketCount;
    public FixedRateTrigger rollTrigger;
    private transient Supplier> groupBySupplier;
    private transient BucketedSlidingWindow, GroupByFlowFunctionWrapper> slidingCalculator;
    private transient final Map mapOfValues = new HashMap<>();
    private transient final MyGroupBy results = new MyGroupBy();


    public GroupByTimedSlidingWindow(
            S inputEventStream,
            SerializableSupplier windowFunctionSupplier,
            @AssignToField("keyFunction")
            SerializableFunction keyFunction,
            @AssignToField("valueFunction")
            SerializableFunction valueFunction,
            @AssignToField("bucketSizeMillis")
            int bucketSizeMillis,
            @AssignToField("bucketCount")
            int bucketCount) {
        super(inputEventStream, null);
        this.windowFunctionSupplier = windowFunctionSupplier;
        this.keyFunction = keyFunction;
        this.valueFunction = valueFunction;
        this.bucketSizeMillis = bucketSizeMillis;
        this.bucketCount = bucketCount;
        resetTriggered = false;
        rollTrigger = FixedRateTrigger.atMillis(bucketSizeMillis);
        groupBySupplier = () -> new GroupByFlowFunctionWrapper<>(keyFunction, valueFunction, windowFunctionSupplier);
        slidingCalculator = new BucketedSlidingWindow<>(groupBySupplier, bucketCount);
    }

    @Override
    public GroupBy get() {
        return results;
    }

    protected void cacheWindowValue() {
        GroupBy value = slidingCalculator.get();
        mapOfValues.clear();
        mapOfValues.putAll(value.toMap());
    }

    protected void aggregateInputValue(S inputEventStream) {
        slidingCalculator.aggregate(inputEventStream.get());
    }

    @OnParentUpdate
    public void timeTriggerFired(FixedRateTrigger rollTrigger) {
        slidingCalculator.roll(rollTrigger.getTriggerCount());
        if (slidingCalculator.isAllBucketsFilled()) {
            cacheWindowValue();
            publishOverrideTriggered = !overridePublishTrigger & !overrideUpdateTrigger;
            inputStreamTriggered_1 = true;
            inputStreamTriggered = true;
        }
    }

    @OnParentUpdate
    public void inputUpdated(S inputEventStream) {
        aggregateInputValue(inputEventStream);
        inputStreamTriggered_1 = false;
        inputStreamTriggered = false;
    }

    @OnParentUpdate("updateTriggerNode")
    public void updateTriggerNodeUpdated(Object triggerNode) {
        super.updateTriggerNodeUpdated(triggerNode);
        cacheWindowValue();
    }

    @Override
    protected void resetOperation() {
        groupBySupplier = () -> new GroupByFlowFunctionWrapper<>(keyFunction, valueFunction, windowFunctionSupplier);
        slidingCalculator = new BucketedSlidingWindow<>(groupBySupplier, bucketCount);
        rollTrigger.init();
        mapOfValues.clear();
    }

    @Override
    public boolean isStatefulFunction() {
        return true;
    }

    @OnTrigger
    public boolean triggered() {
        return fireEventUpdateNotification();
    }

    private class MyGroupBy implements GroupBy {

        @Override
        public Map toMap() {
            return mapOfValues;
        }

        @Override
        public Collection values() {
            return mapOfValues.values();
        }

        @Override
        public R lastValue() {
            return slidingCalculator.get().lastValue();
        }

        @Override
        public KeyValue lastKeyValue() {
            return slidingCalculator.get().lastKeyValue();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy