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

com.github.phantomthief.collection.impl.MultiIntervalTriggerStrategy Maven / Gradle / Ivy

There is a newer version: 0.2.5
Show newest version
package com.github.phantomthief.collection.impl;

import static com.github.phantomthief.collection.impl.SimpleBufferTrigger.TriggerResult.trig;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.Math.abs;
import static java.lang.Math.min;
import static java.lang.System.currentTimeMillis;

import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;

import com.github.phantomthief.collection.impl.SimpleBufferTrigger.TriggerResult;
import com.github.phantomthief.collection.impl.SimpleBufferTrigger.TriggerStrategy;

/**
 * trigger like redis's rdb
 *
 * save 900 1
 * save 300 10
 * save 60 10000
 *
 * 注意,这里的触发条件和 Kafka Producer 的 linger 不一样,并不是 时间和次数达到一个就触发一次
 * 而是指定时间内累计到特定次数才触发,所以一般会有一个兜底的 1 次来做时间触发
 *
 * 更进一步,我们的场景大多数时候一般使用 {@link SimpleBufferTriggerBuilder#interval} 触发就能满足业务的基本需求
 * 所以目前 {@link SimpleBufferTrigger} 没有提供类 Kafka Producer 的 linger 触发模式;
 *
 * @author w.vela
 * Created on 15/07/2016.
 */
public class MultiIntervalTriggerStrategy implements TriggerStrategy {

    private long minTriggerPeriod = Long.MAX_VALUE;
    private final SortedMap triggerMap = new TreeMap<>();

    public MultiIntervalTriggerStrategy on(long interval, TimeUnit unit, long count) {
        long intervalInMs = unit.toMillis(interval);
        triggerMap.put(intervalInMs, count);
        minTriggerPeriod = checkAndCalcMinPeriod();
        return this;
    }

    long minTriggerPeriod() { // for test case
        return minTriggerPeriod;
    }

    private long checkAndCalcMinPeriod() {
        long minPeriod = Long.MAX_VALUE;
        Long maxTrigChangeCount = null;
        long lastPeriod = 0;

        for (Entry entry : triggerMap.entrySet()) {
            long period = entry.getKey();
            minPeriod = min(minPeriod, period);
            if (lastPeriod > 0) {
                minPeriod = min(minPeriod, abs(lastPeriod - period));
            }
            long trigChangedCount = entry.getValue();
            if (maxTrigChangeCount == null) {
                maxTrigChangeCount = trigChangedCount;
            } else {
                if (maxTrigChangeCount <= trigChangedCount) {
                    throw new IllegalArgumentException(
                            "found invalid trigger setting:" + triggerMap);
                }
            }
            lastPeriod = period;
        }
        return minPeriod;
    }

    @Override
    public TriggerResult canTrigger(long lastConsumeTimestamp, long changedCount) {
        checkArgument(!triggerMap.isEmpty());

        boolean doConsumer = false;

        long now = currentTimeMillis();

        for (Entry entry : triggerMap.entrySet()) {
            if (now - lastConsumeTimestamp < entry.getKey()) {
                continue;
            }
            if (changedCount >= entry.getValue()) {
                doConsumer = true;
                break;
            }
        }
        return trig(doConsumer, minTriggerPeriod);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy