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

discord4j.gateway.retry.RetryOptions 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.gateway.retry;

import reactor.core.scheduler.Scheduler;
import reactor.retry.Backoff;
import reactor.retry.BackoffDelay;
import reactor.retry.Jitter;

import java.time.Duration;

/**
 * A configuration object to customize the gateway retry (reconnecting) policy. Tracks reconnection state for a
 * single connection, therefore instances are not shareable across multiple
 * {@link discord4j.gateway.GatewayClient GatewayClients}.
 */
public class RetryOptions {

    private final RetryContext retryContext;
    private final int maxRetries;
    private final Scheduler backoffScheduler;

    /**
     * Create a retry configuration object.
     *
     * @param firstBackoff the Duration to backoff on first attempts
     * @param maxBackoffInterval the maximum backoff Duration
     * @param maxRetries the maximum amount of retries to attempt a reconnect
     * @param scheduler the backoff scheduler used for reconnect delays
     */
    public RetryOptions(Duration firstBackoff, Duration maxBackoffInterval, int maxRetries, Scheduler scheduler) {
        if (firstBackoff.minus(Duration.ofSeconds(2)).isNegative()) {
            throw new IllegalArgumentException("firstBackoff duration must be at least 2 seconds");
        }
        if (maxBackoffInterval.minus(firstBackoff).isNegative()) {
            throw new IllegalArgumentException("maxBackoffInterval must be at least the same as firstBackoff");
        }
        if (maxRetries < 0) {
            throw new IllegalArgumentException("maxRetries must be a positive integer");
        }
        this.retryContext = new RetryContext(firstBackoff, maxBackoffInterval);
        this.maxRetries = maxRetries;
        this.backoffScheduler = scheduler;
    }

    /**
     * Retrieve a stateful context object to hold current attempt count and backoff delay on each retry.
     *
     * @return the RetryContext associated with this configuration object
     */
    public RetryContext getRetryContext() {
        return retryContext;
    }

    /**
     * Retrieve the backoff function used for retrying. It uses a RetryContext object to calculate the correct backoff
     * delay.
     *
     * @return a Backoff function
     */
    public Backoff getBackoff() {
        return context -> {
            RetryContext appContext = (RetryContext) context.applicationContext();
            Duration nextBackoff;
            try {
                long factor = (long) Math.pow(2, (appContext.getAttempts() - 1));
                nextBackoff = appContext.getFirstBackoff().multipliedBy(factor);
            } catch (ArithmeticException e) {
                nextBackoff = appContext.getMaxBackoffInterval();
            }
            return new BackoffDelay(appContext.getFirstBackoff(), appContext.getMaxBackoffInterval(), nextBackoff);
        };
    }

    /**
     * Retrieve the jitter to be applied on each backoff delay.
     *
     * @return a Jitter function
     */
    public Jitter getJitter() {
        return Jitter.random();
    }

    /**
     * Returns the number of retries.
     *
     * @return number of retries
     */
    public int getMaxRetries() {
        return maxRetries;
    }

    /**
     * Returns a scheduler provided every reconnect attempt, as backoff delay.
     *
     * @return scheduler used when reconnecting
     */
    public Scheduler getBackoffScheduler() {
        return backoffScheduler;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy