"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.retry = void 0;
const utils_1 = require("./utils");
const TIMEOUT_STEP_MULTIPLY = 1.2;
const BACKOFF_TIME_STEP_MULTIPLY = 1.2;
const retrySleepResult = "wVgdz8YJgsUud6CPtKYH8tw4mHdLHLbgrEGsGqdWetPDKWAW5hbZ5LMz";
async function retrySleepMs(ms) {
    await (0, utils_1.sleepMs)(ms);
    return retrySleepResult;
}
async function retry(label, 
// eslint-disable-next-line @typescript-eslint/no-explicit-any
funct, timeoutTime = 5000, numRetries = 5, backOddTimeout = 1000, exceptionCallback = utils_1.defaultExceptionCallback, warningCallback = utils_1.defaultWarningCallback, 
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
failure = (label) => { }) {
    try {
        const result = await Promise.race([funct(), retrySleepMs(timeoutTime)]);
        if (result !== retrySleepResult)
            return result;
        // timeout section
        if (numRetries > 0) {
            warningCallback(`retry ^R${label}^^ ${numRetries}`);
            await (0, utils_1.sleepMs)(backOddTimeout / 2 + (0, utils_1.getSimpleRandom)(backOddTimeout / 2));
            return retry(label, funct, timeoutTime * TIMEOUT_STEP_MULTIPLY, numRetries - 1, backOddTimeout * BACKOFF_TIME_STEP_MULTIPLY, exceptionCallback, warningCallback, failure);
        }
        else {
            warningCallback(`retry ^R${label}^^ failed`);
            // failure callback
            failure(label);
            //  return null; // TODO this should probably raise an error
            throw (0, utils_1.MccError)(`retry ^R${label}^^ failed`);
        }
    }
    catch (error) {
        // exception section
        if (numRetries > 0) {
            exceptionCallback(error, `retry ^R${label}^^ exception (retry ${numRetries})`);
            await (0, utils_1.sleepMs)(backOddTimeout / 2 + (0, utils_1.getSimpleRandom)(backOddTimeout / 2));
            return retry(label, funct, timeoutTime * TIMEOUT_STEP_MULTIPLY, numRetries - 1, backOddTimeout * BACKOFF_TIME_STEP_MULTIPLY, exceptionCallback, warningCallback, failure);
        }
        else {
            exceptionCallback(error, `retry ^R${label}^^ exception (retry failed)`);
            // failure callback
            failure(label);
            //  return null;
            throw (0, utils_1.MccError)(error);
        }
    }
}
exports.retry = retry;
//# sourceMappingURL=retry.js.map