UNPKG

@azure/msal-node-extensions

Version:

![npm (scoped)](https://img.shields.io/npm/v/@azure/msal-node-extensions) ![npm](https://img.shields.io/npm/dw/@azure/msal-node-extensions)

96 lines (93 loc) 3.8 kB
/*! @azure/msal-node-extensions v1.5.9 2025-03-25 */ 'use strict'; import { promises } from 'fs'; import { pid } from 'process'; import { Constants } from '../utils/Constants.mjs'; import { PersistenceError } from '../error/PersistenceError.mjs'; import { isNodeError } from '../utils/TypeGuards.mjs'; /* * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ /** * Cross-process lock that works on all platforms. */ class CrossPlatformLock { constructor(lockFilePath, logger, lockOptions) { this.lockFilePath = lockFilePath; this.retryNumber = lockOptions ? lockOptions.retryNumber : 500; this.retryDelay = lockOptions ? lockOptions.retryDelay : 100; this.logger = logger; } /** * Locks cache from read or writes by creating file with same path and name as * cache file but with .lockfile extension. If another process has already created * the lockfile, will back off and retry based on configuration settings set by CrossPlatformLockOptions */ async lock() { for (let tryCount = 0; tryCount < this.retryNumber; tryCount++) { try { this.logger.info(`Pid ${pid} trying to acquire lock`); this.lockFileHandle = await promises.open(this.lockFilePath, "wx+"); this.logger.info(`Pid ${pid} acquired lock`); await this.lockFileHandle.write(pid.toString()); return; } catch (err) { if (isNodeError(err)) { if (err.code === Constants.EEXIST_ERROR || err.code === Constants.EPERM_ERROR) { this.logger.info(err.message); await this.sleep(this.retryDelay); } else { this.logger.error(`${pid} was not able to acquire lock. Ran into error: ${err.message}`); throw PersistenceError.createCrossPlatformLockError(err.message); } } else { throw err; } } } this.logger.error(`${pid} was not able to acquire lock. Exceeded amount of retries set in the options`); throw PersistenceError.createCrossPlatformLockError("Not able to acquire lock. Exceeded amount of retries set in options"); } /** * unlocks cache file by deleting .lockfile. */ async unlock() { try { if (this.lockFileHandle) { // if we have a file handle to the .lockfile, delete lock file await promises.unlink(this.lockFilePath); await this.lockFileHandle.close(); this.logger.info("lockfile deleted"); } else { this.logger.warning("lockfile handle does not exist, so lockfile could not be deleted"); } } catch (err) { if (isNodeError(err)) { if (err.code === Constants.ENOENT_ERROR) { this.logger.info("Tried to unlock but lockfile does not exist"); } else { this.logger.error(`${pid} was not able to release lock. Ran into error: ${err.message}`); throw PersistenceError.createCrossPlatformLockError(err.message); } } else { throw err; } } } sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } } export { CrossPlatformLock }; //# sourceMappingURL=CrossPlatformLock.mjs.map