import fs from "fs";
import os from "os";
const UNLIMITED_CGROUP_THRESHOLD_BYTES = 1 << 60; // treat absurdly large cgroup limit as "unlimited"
export default class MemoryUtil {
    static getHostFreeMemoryInBytes() {
        return os.freemem();
    }
    static getContainerAwareAvailableMemoryInBytes() {
        const hostFreeMemory = this.getHostFreeMemoryInBytes();
        const cgroupAvailableMemory = this.getCgroupAvailableMemoryInBytes();
        if (cgroupAvailableMemory === null) {
            return hostFreeMemory;
        }
        // Be conservative: never exceed container-available memory.
        return Math.min(hostFreeMemory, cgroupAvailableMemory);
    }
    static getCgroupAvailableMemoryInBytes() {
        // cgroup v2
        const v2Limit = this.readNumericFile("/sys/fs/cgroup/memory.max");
        const v2Usage = this.readNumericFile("/sys/fs/cgroup/memory.current");
        if (v2Limit &&
            v2Usage !== null &&
            v2Limit > 0 &&
            v2Limit < UNLIMITED_CGROUP_THRESHOLD_BYTES) {
            return Math.max(v2Limit - v2Usage, 0);
        }
        // cgroup v1
        const v1Limit = this.readNumericFile("/sys/fs/cgroup/memory/memory.limit_in_bytes");
        const v1Usage = this.readNumericFile("/sys/fs/cgroup/memory/memory.usage_in_bytes");
        if (v1Limit &&
            v1Usage !== null &&
            v1Limit > 0 &&
            v1Limit < UNLIMITED_CGROUP_THRESHOLD_BYTES) {
            return Math.max(v1Limit - v1Usage, 0);
        }
        return null;
    }
    static readNumericFile(path) {
        try {
            const rawValue = fs.readFileSync(path, "utf8").trim();
            if (!rawValue || rawValue === "max") {
                return null;
            }
            const value = Number(rawValue);
            if (!Number.isFinite(value) || value <= 0) {
                return null;
            }
            return value;
        }
        catch (_a) {
            return null;
        }
    }
}
//# sourceMappingURL=Memory.js.map