fixed Bucket wait time estimation
All checks were successful
CI / build (push) Successful in 40s

This commit is contained in:
2025-01-25 01:18:05 +08:00
parent 1ab4c3144f
commit 1ff74d28da
2 changed files with 21 additions and 18 deletions

View File

@@ -3,6 +3,6 @@ org.gradle.parallel=true
org.gradle.caching=true org.gradle.caching=true
gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven
jwo.version = 2025.01.23 jwo.version = 2025.01.26
lys.version = 2025.01.17 lys.version = 2025.01.24
guice.version = 5.0.1 guice.version = 5.0.1

View File

@@ -35,12 +35,8 @@ public class LocalBucket implements Bucket {
this.lastFill = new AtomicLong(currentTimestamp); this.lastFill = new AtomicLong(currentTimestamp);
} }
long getTokenPrivate(long nTokens, long now) { private long getTokenPrivate(long nTokens, long now, long previousFillTime, long currentFillTime) {
if(nTokens > maxCapacity) throw new IllegalArgumentException("The requested number of tokens exceeds the bucket max capacity");
final LongBinaryOperator tickCalculator = (lf, currentTimestamp) -> (currentTimestamp - lf) / fillPeriod; final LongBinaryOperator tickCalculator = (lf, currentTimestamp) -> (currentTimestamp - lf) / fillPeriod;
final LongBinaryOperator timestampCalculator = (lf, currentTimestamp) -> lf + tickCalculator.applyAsLong(lf, currentTimestamp) * fillPeriod;
final long previousFillTime = lastFill.getAndAccumulate(now, timestampCalculator);
final long currentFillTime = timestampCalculator.applyAsLong(previousFillTime, now);
if (currentFillTime != previousFillTime) { if (currentFillTime != previousFillTime) {
final long ticks = tickCalculator.applyAsLong(previousFillTime, now); final long ticks = tickCalculator.applyAsLong(previousFillTime, now);
final LongUnaryOperator filledAmountCalculator = currentTokens -> Math.min(currentTokens + ticks * fillAmount, maxCapacity); final LongUnaryOperator filledAmountCalculator = currentTokens -> Math.min(currentTokens + ticks * fillAmount, maxCapacity);
@@ -67,33 +63,40 @@ public class LocalBucket implements Bucket {
} }
} }
@Override @Override
public boolean removeTokens(long nTokens) { public boolean removeTokens(long nTokens) {
return removeTokens(nTokens, System.nanoTime()); return removeTokens(nTokens, System.nanoTime());
} }
@Override @Override
public boolean removeTokens(long nTokens, long currentTimestamp) { public boolean removeTokens(long nTokens, long now) {
return getTokenPrivate(nTokens, currentTimestamp) >= nTokens; if(nTokens > maxCapacity) throw new IllegalArgumentException("The requested number of tokens exceeds the bucket max capacity");
final LongBinaryOperator tickCalculator = (lf, currentTimestamp) -> (currentTimestamp - lf) / fillPeriod;
final LongBinaryOperator timestampCalculator = (lf, currentTimestamp) -> lf + tickCalculator.applyAsLong(lf, currentTimestamp) * fillPeriod;
final long previousFillTime = lastFill.getAndAccumulate(now, timestampCalculator);
final long currentFillTime = timestampCalculator.applyAsLong(previousFillTime, now);
long result = getTokenPrivate(nTokens, now, previousFillTime, currentFillTime);
return result >= nTokens;
} }
@Override @Override
public long removeTokensWithEstimate(long nTokens) { public long removeTokensWithEstimate(long nTokens) {
final long previousTokenAmount = getTokenPrivate(nTokens, System.nanoTime()); return removeTokensWithEstimate(nTokens, System.nanoTime());
if(previousTokenAmount >= nTokens) {
return -1;
} else {
return ceilDiv((nTokens - previousTokenAmount) * fillPeriod, fillAmount);
}
} }
@Override @Override
public long removeTokensWithEstimate(long nTokens, long currentTimestamp) { public long removeTokensWithEstimate(long nTokens, long now) {
final long previousTokenAmount = getTokenPrivate(nTokens, currentTimestamp); if(nTokens > maxCapacity) throw new IllegalArgumentException("The requested number of tokens exceeds the bucket max capacity");
final LongBinaryOperator tickCalculator = (lf, currentTimestamp) -> (currentTimestamp - lf) / fillPeriod;
final LongBinaryOperator timestampCalculator = (lf, currentTimestamp) -> lf + tickCalculator.applyAsLong(lf, currentTimestamp) * fillPeriod;
final long previousFillTime = lastFill.getAndAccumulate(now, timestampCalculator);
final long currentFillTime = timestampCalculator.applyAsLong(previousFillTime, now);
long previousTokenAmount = getTokenPrivate(nTokens, now, previousFillTime, currentFillTime);
if(previousTokenAmount >= nTokens) { if(previousTokenAmount >= nTokens) {
return -1; return -1;
} else { } else {
return ceilDiv((nTokens - previousTokenAmount) * fillPeriod, fillAmount); return Math.max(ceilDiv((nTokens - previousTokenAmount) * fillPeriod, fillAmount), currentFillTime + fillPeriod - now);
} }
} }
} }