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

discord4j.common.SimpleBucket Maven / Gradle / Ivy

/*
 * This file is part of Discord4J.
 *
 * Discord4J is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Discord4J is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Discord4J. If not, see .
 */

package discord4j.common;

import java.time.Duration;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Naive implementation of a rate-limiter that issues a certain amount of permits before requiring consumers to wait
 * until the permits are refilled.
 */
public class SimpleBucket implements RateLimiter {

    private final long capacity;
    private final long refillPeriodMillis;

    private final AtomicLong count;
    private final AtomicLong nextRefillAt;

    public SimpleBucket(long capacity, Duration refillPeriod) {
        this.capacity = capacity;
        this.refillPeriodMillis = refillPeriod.toMillis();
        this.count = new AtomicLong(0);
        this.nextRefillAt = new AtomicLong(0);
    }

    @Override
    public synchronized boolean tryConsume(int numberTokens) {
        long now = System.currentTimeMillis();
        if (nextRefillAt.get() <= now) {
            count.set(0);
            nextRefillAt.set(now + refillPeriodMillis);
        }
        if (count.get() + numberTokens <= capacity) {
            count.addAndGet(numberTokens);
            return true;
        }
        return false;
    }

    @Override
    public synchronized long delayMillisToConsume(long tokens) {
        if (count.get() + tokens <= capacity) {
            return 0;
        }
        long now = System.currentTimeMillis();
        long refills = (long) Math.ceil((tokens / (double) capacity) - 1);
        return (nextRefillAt.get() - now) + (refillPeriodMillis * refills);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy