"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.onStorageReclamation = onStorageReclamation;
exports.runReclamationHandlers = runReclamationHandlers;
exports.setAvailableSpaceRatioGetter = setAvailableSpaceRatioGetter;
const promises_1 = require("node:fs/promises");
const manageThreads_js_1 = require("../server/threads/manageThreads.js");
const logger_ts_1 = require("../utility/logging/logger.js");
const hdbTerms_ts_1 = require("../utility/hdbTerms.js");
const environmentManager_js_1 = __importDefault(require("../utility/environment/environmentManager.js"));
const common_utils_js_1 = require("../utility/common_utils.js");
environmentManager_js_1.default.initSync();
const reclamationHandlers = new Map();
const RECLAMATION_THRESHOLD = environmentManager_js_1.default.get(hdbTerms_ts_1.CONFIG_PARAMS.STORAGE_RECLAMATION_THRESHOLD) ?? 0.4; // 40% remaining free space is the default
const RECLAMATION_INTERVAL = (0, common_utils_js_1.convertToMS)(environmentManager_js_1.default.get(hdbTerms_ts_1.CONFIG_PARAMS.STORAGE_RECLAMATION_INTERVAL)) || 3600000; // 1 hour is the default
/**
 * Register a handler to be called when storage free space is low and reclamation is needed. The callback is called
 * with the priority of the reclamation, which is the ratio of the threshold to the available space ratio. If space is
 * low, the priority will be greater than 1. If the reclamation is successful, the callback will be called again with
 * a priority of 0.
 * @param path
 * @param handler
 * @param skipThreadCheck
 */
function onStorageReclamation(path, handler, skipThreadCheck) {
    if (skipThreadCheck || (0, manageThreads_js_1.getWorkerIndex)() === (0, manageThreads_js_1.getWorkerCount)() - 1) {
        // only run on one thread (last one)
        if (!path) {
            throw new Error('Storage reclamation path cannot be empty');
        }
        if (!reclamationHandlers.has(path)) {
            reclamationHandlers.set(path, []);
        }
        reclamationHandlers.get(path).push({ priority: 0, handler });
        if (!reclamationTimer)
            reclamationTimer = setTimeout(runReclamationHandlers, RECLAMATION_INTERVAL).unref();
    }
}
let reclamationTimer;
const defaultGetAvailableSpaceRatio = async (path) => {
    const fsStats = await (0, promises_1.statfs)(path);
    return fsStats.bavail / fsStats.blocks;
};
let getAvailableSpaceRatio = defaultGetAvailableSpaceRatio;
/**
 * Run the registered reclamation handlers, if any disk drives are below the threshold
 */
async function runReclamationHandlers() {
    for (const [path, handlers] of reclamationHandlers) {
        try {
            const availableRatio = await getAvailableSpaceRatio(path);
            const priority = RECLAMATION_THRESHOLD / availableRatio;
            for (const entry of handlers) {
                const { priority: previousPriority, handler } = entry;
                entry.priority = priority;
                if (priority > 1 || previousPriority > 1) {
                    const resolution = handler(priority > 1 ? priority : 0);
                    if (resolution) {
                        // if the handler returns a promise, wait for it, otherwise it is probably not doing anything worth logging
                        logger_ts_1.logger.info?.(`Running storage reclamation handler for ${path} with priority ${priority}`);
                        await resolution;
                    }
                }
            }
        }
        catch (e) {
            logger_ts_1.logger.error?.('Error running storage reclamation handlers', e);
        }
    }
    reclamationTimer = setTimeout(runReclamationHandlers, RECLAMATION_INTERVAL).unref();
}
/**
 * Set the function used to get the available space ratio (for testing and backfill for Node v16)
 * @param newGetter
 */
function setAvailableSpaceRatioGetter(newGetter) {
    getAvailableSpaceRatio = newGetter ?? defaultGetAvailableSpaceRatio;
}
//# sourceMappingURL=storageReclamation.js.map