"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setJitterTimeout = setJitterTimeout;
exports.retryFunction = retryFunction;
const global_logger_factory_1 = require("global-logger-factory");
const InternalServerError_1 = require("./errors/InternalServerError");
const logger = (0, global_logger_factory_1.getLoggerFor)('LockUtil');
/**
 * Waits a set amount of time, without consuming cpu, with a set amount of jitter.
 *
 * @param delay - How long to wait.
 * @param jitter - A fraction of this jitter will be added to the delay.
 *
 * @returns A promise that resolves after the specified amount of time.
 */
async function setJitterTimeout(delay, jitter = 0) {
    jitter = Math.max(0, Math.floor(Math.random() * jitter));
    delay = Math.max(0, delay + jitter);
    return new Promise((resolve) => setTimeout(resolve, delay));
}
/**
 * Will execute the given function until one of the following cases occurs:
 * * The function resolves to a value: the value is returned.
 * * The function errors: the rejected error is thrown.
 * * The function did not resolve after the set amount of retries: the rejected error is returned.
 *
 * @param fn - The function to retry. **This function must return a value!**
 * @param settings - The options on how to retry the function
 */
async function retryFunction(fn, settings) {
    const { retryCount, retryDelay, retryJitter } = settings;
    const maxTries = retryCount === -1 ? Number.POSITIVE_INFINITY : retryCount + 1;
    let tries = 1;
    let result = await fn();
    while (typeof result === 'undefined' && tries < maxTries) {
        await setJitterTimeout(retryDelay, retryJitter);
        result = await fn();
        tries += 1;
    }
    // Max tries was reached: throw first!
    if (tries >= maxTries) {
        const err = `The operation did not succeed after the set maximum of tries (${maxTries}).`;
        logger.warn(err);
        throw new InternalServerError_1.InternalServerError(err);
    }
    return result;
}
//# sourceMappingURL=LockUtils.js.map