"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.end = end;
exports.get = get;
exports.set = set;
exports.init = init;
/* istanbul ignore file */
const luxon_1 = require("luxon");
const redis_1 = require("redis");
const logger_1 = require("../../../logger");
const compress_1 = require("../../compress");
let client;
let rprefix;
function getKey(namespace, key) {
    return `${rprefix}${namespace}-${key}`;
}
async function end() {
    try {
        // https://github.com/redis/node-redis#disconnecting
        await client?.disconnect();
    }
    catch (err) {
        logger_1.logger.warn({ err }, 'Redis cache end failed');
    }
}
async function rm(namespace, key) {
    logger_1.logger.trace({ rprefix, namespace, key }, 'Removing cache entry');
    await client?.del(getKey(namespace, key));
}
async function get(namespace, key) {
    if (!client) {
        return undefined;
    }
    logger_1.logger.trace(`cache.get(${namespace}, ${key})`);
    try {
        const res = await client?.get(getKey(namespace, key));
        const cachedValue = res && JSON.parse(res);
        if (cachedValue) {
            if (luxon_1.DateTime.local() < luxon_1.DateTime.fromISO(cachedValue.expiry)) {
                logger_1.logger.trace({ rprefix, namespace, key }, 'Returning cached value');
                // istanbul ignore if
                if (!cachedValue.compress) {
                    return cachedValue.value;
                }
                const res = await (0, compress_1.decompressFromBase64)(cachedValue.value);
                return JSON.parse(res);
            }
            // istanbul ignore next
            await rm(namespace, key);
        }
    }
    catch (err) {
        logger_1.logger.trace({ rprefix, namespace, key }, 'Cache miss');
    }
    return undefined;
}
async function set(namespace, key, value, ttlMinutes = 5) {
    logger_1.logger.trace({ rprefix, namespace, key, ttlMinutes }, 'Saving cached value');
    // Redis requires TTL to be integer, not float
    const redisTTL = Math.floor(ttlMinutes * 60);
    try {
        await client?.set(getKey(namespace, key), JSON.stringify({
            compress: true,
            value: await (0, compress_1.compressToBase64)(JSON.stringify(value)),
            expiry: luxon_1.DateTime.local().plus({ minutes: ttlMinutes }),
        }), { EX: redisTTL });
    }
    catch (err) {
        logger_1.logger.once.warn({ err }, 'Error while setting Redis cache value');
    }
}
async function init(url, prefix) {
    if (!url) {
        return;
    }
    rprefix = prefix ?? '';
    logger_1.logger.debug('Redis cache init');
    client = (0, redis_1.createClient)({
        url,
        socket: {
            reconnectStrategy: (retries) => {
                // Reconnect after this time
                return Math.min(retries * 100, 3000);
            },
        },
        pingInterval: 30000, // 30s
    });
    await client.connect();
    logger_1.logger.debug('Redis cache connected');
}
//# sourceMappingURL=redis.js.map