package com.echsylon.kraken;

/**
 * Created by laszlo on 2017-08-25.
 */
final class CallCounter {
    private final int decreaseInterval;
    private final int maxCount;

    private long lastCallTime;
    private int callCounter;

    CallCounter(int tier) {
        lastCallTime = 0L;
        callCounter = 0;

        switch (tier) {
            case 4:
                maxCount = 20;
                decreaseInterval = 1;
                break;
            case 3:
                maxCount = 20;
                decreaseInterval = 2;
                break;
            case 2: // Intentional fallthrough
            case 1:
            case 0:
            default:
                maxCount = 15;
                decreaseInterval = 3;
                break;
        }
    }

    synchronized void allocate(int cost) {
        // Early bail-out
        if (lastCallTime == 0L) {
            callCounter += cost;
            lastCallTime = System.currentTimeMillis() / 1000L;
            return;
        }

        // Calculate the number of seconds since last call.
        long currentTime = System.currentTimeMillis() / 1000L;
        long durationSinceLastCall = currentTime - lastCallTime;

        // Update the call counter accordingly
        int reduction = (int) (durationSinceLastCall / decreaseInterval);
        callCounter = Math.max(0, callCounter - reduction);
        callCounter += cost;

        // Wait for the call counter to chill down
        if (callCounter > maxCount)
            try {
                Thread.sleep((callCounter - maxCount) * decreaseInterval * 1000L);
                callCounter = maxCount;
            } catch (InterruptedException e) {
                // Oh dear!
            }

        // Update the last call timestamp
        lastCallTime = System.currentTimeMillis() / 1000L;
    }

}

@@ -34,39 +34,147 @@
 %0A * 
-Created by laszlo on 2017-08-25
+This class know how to calculate the call rate limit state for API requests%0A * and will temporary block the thread if the limit is exceeded
 .%0A *
@@ -335,16 +335,233 @@
 unter;%0A%0A
+%0A    /**%0A     * Creates a new call rate state machine and initializes it with rules%0A     * according to the supplied tier.%0A     *%0A     * @param tier The tier that decides which call rate limit rules to apply.%0A     */%0A
     Call
@@ -1094,24 +1094,381 @@
    %7D%0A    %7D%0A%0A
+%0A    /**%0A     * Calculates the next state of the call rate state machine according to the%0A     * supplied request cost. If the call rate limit is exceeded, the calling%0A     * thread is blocked to allow the call counter to chill down and allow the%0A     * request to proceed.%0A     *%0A     * @param cost The cost of the request being handled right now.%0A     */%0A
     synchron

Update JavaDoc