"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isCosmosDbRateLimitError = isCosmosDbRateLimitError;
exports.getRetryAfterMs = getRetryAfterMs;
exports.retryWithCosmosDbBackoff = retryWithCosmosDbBackoff;
const logger_1 = __importDefault(require("../logger"));
/**
 * Checks if an error is a Cosmos DB rate limit error (429)
 */
function isCosmosDbRateLimitError(error) {
    if (!error)
        return false;
    const errorMessage = error.message || error.toString() || '';
    const errorCode = error.code || error.statusCode;
    // Check for Cosmos DB specific error indicators
    return (errorCode === 429 ||
        errorCode === 16500 || // Cosmos DB specific error code
        errorMessage.includes('TooManyRequests') ||
        errorMessage.includes('Request rate is large') ||
        errorMessage.includes('More Request Units may be needed') ||
        errorMessage.includes('cosmosdb-error-429'));
}
/**
 * Extracts retry delay from Cosmos DB error response
 */
function getRetryAfterMs(error) {
    // Check for RetryAfterMs in error details
    if (error.RetryAfterMs && typeof error.RetryAfterMs === 'number') {
        return error.RetryAfterMs;
    }
    // Check for retry-after in error message
    const errorMessage = error.message || error.toString() || '';
    const retryAfterMatch = errorMessage.match(/RetryAfterMs[=:]?\s*(\d+)/i);
    if (retryAfterMatch) {
        return Number.parseInt(retryAfterMatch[1], 10);
    }
    // Default exponential backoff: start with 500ms, increase with each retry
    return 500;
}
/**
 * Sleep utility
 */
function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
 * Retries an operation with exponential backoff when Cosmos DB rate limits are encountered
 *
 * @param operation - The async operation to retry
 * @param maxRetries - Maximum number of retries (default: 5)
 * @param baseDelayMs - Base delay in milliseconds (default: 500)
 * @returns The result of the operation
 */
async function retryWithCosmosDbBackoff(operation, maxRetries = 5, baseDelayMs = 500) {
    let lastError;
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
        try {
            return await operation();
        }
        catch (error) {
            lastError = error;
            // Check if it's a Cosmos DB rate limit error
            if (isCosmosDbRateLimitError(error)) {
                const retryAfter = getRetryAfterMs(error);
                const delay = attempt === 0 ? retryAfter : Math.min(retryAfter * Math.pow(2, attempt), 30000); // Cap at 30 seconds
                if (attempt < maxRetries) {
                    logger_1.default.warn(`Cosmos DB rate limit encountered (attempt ${attempt + 1}/${maxRetries + 1}). ` +
                        `Retrying after ${delay}ms...`);
                    await sleep(delay);
                    continue;
                }
                else {
                    logger_1.default.error(`Cosmos DB rate limit error after ${maxRetries + 1} attempts. ` +
                        `Please increase Request Units (RUs) or reduce request rate.`);
                }
            }
            // If it's not a rate limit error or we've exhausted retries, throw
            throw error;
        }
    }
    throw lastError;
}
//# sourceMappingURL=cosmosDbRetry.js.map