package org.distributeme.core.routing.blacklisting;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* Created by rboehling on 2/24/17.
*/
class ErrorCounter {
private AtomicInteger currentIntervalErrorCounter = new AtomicInteger();
private AtomicInteger nonStopIntervalsWithErrorsCounter = new AtomicInteger();
private final ErrorsPerIntervalBlacklistingStrategyConfig config;
private AtomicLong startTime = new AtomicLong(0);
private volatile BlacklistDecision previousDecision = BlacklistDecision.NOT_BLACKLISTED;
ErrorCounter(ErrorsPerIntervalBlacklistingStrategyConfig config) {
this.config = config;
}
BlacklistDecision isBlacklisted() {
BlacklistDecision currentDecision;
boolean isCurrentlyBlacklisted = reachedRequiredNumberOfIntervalsWithErrors() || reachRequiredNumberOfIntervalsWithErrorsWithCurrentInterval();
if(isCurrentlyBlacklisted) {
currentDecision = previousDecision.isBlacklisted() ?
BlacklistDecision.IS_BLACKLISTED : BlacklistDecision.GOT_BLACKLISTED;
} else {
currentDecision = previousDecision.isBlacklisted() ?
BlacklistDecision.UNBLACKLISTED : BlacklistDecision.NOT_BLACKLISTED;
}
previousDecision = currentDecision;
return currentDecision;
}
private boolean reachedRequiredNumberOfIntervalsWithErrors() {
return nonStopIntervalsWithErrorsCounter.get() >= config.getRequiredNumberOfIntervalsWithErrors();
}
private boolean reachRequiredNumberOfIntervalsWithErrorsWithCurrentInterval() {
return reachedThresholdWithinCurrentInterval() && nonStopIntervalsWithErrorsCounter.get() >= config.getRequiredNumberOfIntervalsWithErrors() - 1;
}
private boolean reachedThresholdWithinCurrentInterval() {
return currentIntervalErrorCounter.get() >= config.getErrorsPerIntervalThreshold();
}
private void setNonStopIntervalsWithErrorCounter() {
if (reachedThresholdWithinCurrentInterval()) {
nonStopIntervalsWithErrorsCounter.incrementAndGet();
} else {
nonStopIntervalsWithErrorsCounter.set(0);
}
}
void notifyCallFailed() {
currentIntervalErrorCounter.incrementAndGet();
}
void timerTick(long currentTimeMillis) {
if (isIntervalDurationReached(currentTimeMillis)) {
setNonStopIntervalsWithErrorCounter();
currentIntervalErrorCounter.set(0);
startTime.set(currentTimeMillis);
}
}
private boolean isIntervalDurationReached(long currentTimeMillis) {
return ((currentTimeMillis - startTime.get()) / 1000) >= config.getIntervalDurationInSeconds();
}
}