UNPKG

@aikidosec/firewall

Version:

Zen by Aikido is an embedded Application Firewall that autonomously protects Node.js apps against common and critical attacks, provides rate limiting, detects malicious traffic (including bots), and more.

66 lines (65 loc) 2.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LockFile = void 0; const promises_1 = require("fs/promises"); const promises_2 = require("timers/promises"); const path_1 = require("path"); const os_1 = require("os"); const isUnitTest_1 = require("./isUnitTest"); const LOCK_DIR = (0, path_1.join)((0, os_1.tmpdir)(), "zen-test-locks"); class LockFile { constructor(name) { this.handle = null; if (!(0, isUnitTest_1.isUnitTest)()) { throw new Error("LockFile can only be used in unit tests"); } this.lockFile = (0, path_1.join)(LOCK_DIR, `${name}.lock`); } async acquire() { // Ensure lock directory exists await (0, promises_1.mkdir)(LOCK_DIR, { recursive: true }); // Use wx flag to create file exclusively (fails if file exists) const maxRetries = 1000; const retryDelay = 100; // 100ms for (let i = 0; i < maxRetries; i++) { try { this.handle = await (0, promises_1.open)(this.lockFile, "wx"); return; // Lock acquired successfully } catch (error) { if (error.code === "EEXIST") { // Lock file exists, wait and retry await (0, promises_2.setTimeout)(retryDelay); continue; } throw error; } } throw new Error(`Failed to acquire lock after ${maxRetries} attempts`); } async release() { if (this.handle) { await this.handle.close(); this.handle = null; } try { await (0, promises_1.unlink)(this.lockFile); } catch (error) { // Ignore ENOENT errors (file already doesn't exist) if (error.code !== "ENOENT") { throw error; } } } async withLock(fn) { await this.acquire(); try { return await fn(); } finally { await this.release(); } } } exports.LockFile = LockFile;