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

discord4j.rest.request.GlobalRateLimiter 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.rest.request;

import reactor.core.publisher.EmitterProcessor;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.Logger;
import reactor.util.Loggers;

import java.time.Duration;

/**
 * Used to prevent requests from being sent while the bot is
 * globally ratelimited.
 * 

* When subscribing to the rate limiter, the only guarantee is that the subscription will be completed at some point in * the future. If a global ratelimit is in effect, it will be completed when the cooldown ends. Otherwise, it is * completed immediately. */ public class GlobalRateLimiter { private static final Logger log = Loggers.getLogger(GlobalRateLimiter.class); private static final Object PERMIT = new Object(); private final EmitterProcessor resetNotifier = EmitterProcessor.create(false); private volatile boolean isRateLimited; private final Flux flux = Flux.create(sink -> sink.onRequest(l -> { if (isRateLimited) { resetNotifier.next().subscribe(o -> sink.complete(), t -> log.error("Could not reset global notifier", t)); } else { sink.complete(); } })); /** * Prevents the rate limiter from completing subscriptions for the given duration. * * @param duration The duration to prevent completions for. */ void rateLimitFor(Duration duration) { if (log.isTraceEnabled()) { log.trace("Setting a global rate limit for {}", duration); } isRateLimited = true; Mono.delay(duration).subscribe(l -> { if (log.isTraceEnabled()) { log.trace("Global rate limit has completed after {}", duration); } isRateLimited = false; resetNotifier.onNext(PERMIT); }, t -> log.error("Error while resolving global rate limiter", t)); } public Mono onComplete() { return flux.then(); } }