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

com.github.phantomthief.failover.impl.WeightFailoverBuilder Maven / Gradle / Ivy

package com.github.phantomthief.failover.impl;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static org.slf4j.LoggerFactory.getLogger;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.IntUnaryOperator;
import java.util.function.Predicate;

import javax.annotation.CheckReturnValue;

import org.slf4j.Logger;

public class WeightFailoverBuilder {

    private static final Logger logger = getLogger(WeightFailoverBuilder.class);

    private static final int DEFAULT_INIT_WEIGHT = 100;
    private static final int DEFAULT_FAIL_REDUCE_WEIGHT = 5;
    private static final int DEFAULT_SUCCESS_INCREASE_WEIGHT = 1;
    private static final int DEFAULT_RECOVERED_INIT_WEIGHT = 1;
    private static final long DEFAULT_CHECK_DURATION = SECONDS.toMillis(1);

    private IntUnaryOperator failReduceWeight;
    private IntUnaryOperator successIncreaseWeight;
    private IntUnaryOperator recoveredInitWeight;

    private Map initWeightMap;
    private Predicate checker;
    private long checkDuration;
    private Consumer onMinWeight;
    private Consumer onRecovered;
    private int minWeight = 0;

    @CheckReturnValue
    @SuppressWarnings("unchecked")
    public  WeightFailoverBuilder onMinWeight(Consumer listener) {
        checkNotNull(listener);
        WeightFailoverBuilder thisBuilder = (WeightFailoverBuilder) this;
        thisBuilder.onMinWeight = listener;
        return thisBuilder;
    }

    @CheckReturnValue
    @SuppressWarnings("unchecked")
    public  WeightFailoverBuilder onRecovered(Consumer listener) {
        checkNotNull(listener);
        WeightFailoverBuilder thisBuilder = (WeightFailoverBuilder) this;
        thisBuilder.onRecovered = listener;
        return thisBuilder;
    }

    @CheckReturnValue
    public WeightFailoverBuilder minWeight(int value) {
        checkArgument(value >= 0);
        this.minWeight = value;
        return this;
    }

    @CheckReturnValue
    public WeightFailoverBuilder failReduceRate(double rate) {
        checkArgument(rate > 0 && rate <= 1);
        failReduceWeight = i -> Math.max(1, (int) (rate * i));
        return this;
    }

    @CheckReturnValue
    public WeightFailoverBuilder failReduce(int weight) {
        checkArgument(weight > 0);
        failReduceWeight = i -> weight;
        return this;
    }

    @CheckReturnValue
    public WeightFailoverBuilder successIncreaseRate(double rate) {
        checkArgument(rate > 0 && rate <= 1);
        successIncreaseWeight = i -> Math.max(1, (int) (rate * i));
        return this;
    }

    @CheckReturnValue
    public WeightFailoverBuilder successIncrease(int weight) {
        checkArgument(weight > 0);
        successIncreaseWeight = i -> weight;
        return this;
    }

    @CheckReturnValue
    public WeightFailoverBuilder recoveredInitRate(double rate) {
        checkArgument(rate > 0 && rate <= 1);
        recoveredInitWeight = i -> Math.max(1, (int) (rate * i));
        return this;
    }

    @CheckReturnValue
    public WeightFailoverBuilder recoveredInit(int weight) {
        checkArgument(weight > 0);
        recoveredInitWeight = i -> weight;
        return this;
    }

    @CheckReturnValue
    public WeightFailoverBuilder checkDuration(long time, TimeUnit unit) {
        checkNotNull(unit);
        checkArgument(time > 0);
        checkDuration = unit.toMillis(time);
        return this;
    }

    @SuppressWarnings("unchecked")
    @CheckReturnValue
    public  WeightFailoverBuilder checker(Predicate failChecker) {
        checkNotNull(failChecker);
        WeightFailoverBuilder thisBuilder = (WeightFailoverBuilder) this;
        thisBuilder.checker = t -> {
            try {
                return failChecker.test(t);
            } catch (Throwable e) {
                logger.error("", e);
                return false;
            }
        };
        return thisBuilder;
    }

    public  WeightFailover build(Collection original) {
        return build(original, DEFAULT_INIT_WEIGHT);
    }

    public  WeightFailover build(Collection original, int initWeight) {
        checkNotNull(original);
        checkArgument(initWeight > 0);
        return build(original.stream().collect(toMap(identity(), i -> initWeight, (u, v) -> u)));
    }

    @SuppressWarnings("unchecked")
    public  WeightFailover build(Map original) {
        checkNotNull(original);
        WeightFailoverBuilder thisBuilder = (WeightFailoverBuilder) this;
        thisBuilder.initWeightMap = (Map) original;
        return thisBuilder.build();
    }

    private WeightFailover build() {
        ensure();
        return new WeightFailover<>(failReduceWeight, successIncreaseWeight, recoveredInitWeight,
                initWeightMap, minWeight, checkDuration, checker, onMinWeight, onRecovered);
    }

    private void ensure() {
        checkNotNull(checker);
        if (failReduceWeight == null) {
            failReduceWeight = i -> DEFAULT_FAIL_REDUCE_WEIGHT;
        }
        if (successIncreaseWeight == null) {
            successIncreaseWeight = i -> DEFAULT_SUCCESS_INCREASE_WEIGHT;
        }
        if (recoveredInitWeight == null) {
            recoveredInitWeight = i -> DEFAULT_RECOVERED_INIT_WEIGHT;
        }
        if (checkDuration == 0) {
            checkDuration = DEFAULT_CHECK_DURATION;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy