### Configuration Options Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Explanation of constructor options for Mutex and Semaphore, including initialization patterns and setup examples. ```APIDOC ## Configuration Options This section details the configuration options available for initializing Mutex and Semaphore instances. ### Constructor Options #### Mutex Options: - `delay`: The time in milliseconds to wait between retries when the lock is contended. Defaults to `100`. - `maxRetries`: The maximum number of times to retry acquiring the lock. Defaults to `Infinity`. - `onTimeout`: A function to call when a timeout occurs. This function receives the timeout duration as an argument. #### Semaphore Options: - `delay`: The time in milliseconds to wait between retries when permits are contended. Defaults to `100`. - `maxRetries`: The maximum number of times to retry acquiring a permit. Defaults to `Infinity`. - `onTimeout`: A function to call when a timeout occurs. This function receives the timeout duration as an argument. ### Initialization Patterns ```javascript import { Mutex, Semaphore } from 'async-mutex'; // Mutex with custom retry delay and max retries const customMutex = new Mutex({ delay: 50, maxRetries: 5 }); // Semaphore with a timeout error handler const semaphore = new Semaphore(3, { onTimeout: (ms) => { console.warn(`Semaphore acquisition timed out after ${ms}ms`); } }); ``` ``` -------------------------------- ### Install async-mutex using npm Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/README.md Install the async-mutex package using npm. This is the first step before importing and using the library. ```bash npm install async-mutex ``` -------------------------------- ### TypeScript Configuration Example Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/configuration.md Example tsconfig.json settings for projects using async-mutex. The library provides full TypeScript type definitions, so no special compiler options are strictly required beyond standard ES module support. ```json { "compilerOptions": { "target": "es2015", "lib": ["es2015", "dom"], "module": "commonjs" } } ``` -------------------------------- ### CommonJS Require Example Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/EXPORTS.md Shows how to import all exported components from the async-mutex library using CommonJS require syntax. ```javascript const { Mutex, Semaphore, MutexInterface, SemaphoreInterface, withTimeout, tryAcquire, E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED } = require('async-mutex'); ``` -------------------------------- ### withTimeout Usage Example Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/withTimeout.md Demonstrates how to use the withTimeout utility to acquire a lock with a specified timeout and custom error. ```APIDOC ## withTimeout Usage Example ### Description This example shows how to wrap a Mutex with a timeout using the `withTimeout` utility. If the lock acquisition exceeds the specified timeout (500ms in this case), the promise will reject with a custom error message. ### Method N/A (This is a utility function, not an HTTP endpoint) ### Endpoint N/A ### Parameters N/A for the utility function itself, but it wraps a Mutex. ### Request Example ```typescript import { Mutex, withTimeout } from 'async-mutex'; const mutexWithTimeout = withTimeout( new Mutex(), 500, new Error('Lock acquisition timeout') ); try { await mutexWithTimeout.acquire(); } catch (error) { console.error(error.message); // "Lock acquisition timeout" } ``` ### Response N/A (This is a code example demonstrating usage, not an API response) ### Error Handling - If the timeout occurs before the lock is acquired, the promise rejects. - Custom errors can be provided to `withTimeout`. ``` -------------------------------- ### ES6 Import Example Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/EXPORTS.md Illustrates importing all library components using standard ES6 import syntax, suitable for modern JavaScript environments. ```javascript import { Mutex, Semaphore, MutexInterface, SemaphoreInterface, withTimeout, tryAcquire, E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED } from 'async-mutex'; ``` -------------------------------- ### Usage Scenarios Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Examples of common usage scenarios for the async-mutex library, including basic locking, concurrency limiting, and pattern implementations. ```APIDOC ## Usage Scenarios This section illustrates various practical applications of the async-mutex library. ### Basic Mutex Locking Demonstrates the fundamental use of `Mutex` for ensuring exclusive access. ### Basic Semaphore Locking Shows how to use `Semaphore` to control concurrent access to a limited number of resources. ### Timeout with Fallback Illustrates implementing a timeout for lock acquisition with a fallback mechanism. ### Non-blocking with Retry Provides an example of attempting to acquire a lock without blocking and implementing a retry strategy. ### Concurrent Operation Limiting Shows how to limit the number of concurrent operations using a semaphore. ### Per-Resource Locking Demonstrates locking individual resources within a collection. ### Priority Scheduling Illustrates how to leverage priority-based scheduling for task execution. ### Custom Error Messages Shows how to configure and handle custom error messages during lock operations. ### Web Crawler Patterns Examples of using mutexes/semaphores in web crawling scenarios to manage request rates or concurrent fetches. ### Factory Patterns Illustrates using async-mutex within factory patterns to manage resource creation or initialization. ### Pool Patterns Demonstrates implementing resource pools with controlled access using semaphores. ``` -------------------------------- ### Implement Custom Mutex Class Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/types.md Provides an example of implementing the MutexInterface with a custom class, including acquire and runExclusive methods. ```typescript import { MutexInterface } from 'async-mutex'; class CustomMutex implements MutexInterface { async acquire(priority?: number): Promise { // Custom implementation return () => {}; } runExclusive(callback: MutexInterface.Worker, priority?: number): Promise { // Custom implementation return callback(); } // ... implement remaining methods } ``` -------------------------------- ### Basic withTimeout() Usage Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/configuration.md Demonstrates how to apply timeout functionality to a Mutex and a Semaphore. Includes examples for setting a custom timeout error. ```typescript import { Mutex, Semaphore, withTimeout } from 'async-mutex'; // Mutex with 5-second timeout const mutex = withTimeout(new Mutex(), 5000); // Semaphore with 100-millisecond timeout const semaphore = withTimeout(new Semaphore(2), 100); // With custom timeout error const timedMutex = withTimeout( new Mutex(), 3000, new Error('Operation took too long') ); // With class-based custom error class TimeoutError extends Error { constructor(operation: string) { super(`${operation} timed out`); this.name = 'TimeoutError'; } } const customTimedMutex = withTimeout( new Mutex(), 2000, new TimeoutError('Lock acquisition') ); ``` -------------------------------- ### TypeScript Import Example Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/EXPORTS.md Demonstrates how to import all available components, including classes, interfaces, functions, and error constants, using TypeScript's ES6 import syntax. ```typescript import { // Classes Mutex, Semaphore, // Interfaces MutexInterface, SemaphoreInterface, // Functions withTimeout, tryAcquire, // Error constants E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED } from 'async-mutex'; ``` -------------------------------- ### Decorating Mutex and Semaphore with tryAcquire Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Shows how to use tryAcquire to wrap a Mutex and a Semaphore, enabling non-blocking access. Includes examples of using the default error and providing a custom error object. ```typescript import { Mutex, Semaphore, tryAcquire, E_ALREADY_LOCKED } from 'async-mutex'; // Decorate a mutex with non-blocking behavior const mutex = new Mutex(); const nonBlockingMutex = tryAcquire(mutex); // Decorate a semaphore const semaphore = new Semaphore(2); const nonBlockingSemaphore = tryAcquire(semaphore); // With custom error const customMutex = tryAcquire( new Mutex(), new Error('Resource is busy') ); ``` -------------------------------- ### Non-blocking Semaphore RunExclusive Example Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Shows how to attempt to execute a callback with a semaphore lock using a non-blocking approach. If the lock cannot be acquired immediately, the operation is skipped. ```typescript const nonBlockingSemaphore = tryAcquire(new Semaphore(1)); try { const result = await nonBlockingSemaphore.runExclusive(async (value) => { console.log('Executing with value:', value); return await performWork(); }); } catch (error) { if (error === E_ALREADY_LOCKED) { console.log('Could not acquire lock, skipping operation'); } } ``` -------------------------------- ### Semaphore Creation Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Creates a new semaphore with an initial value. The initial value is an arbitrary integer that defines the starting value of the semaphore. ```APIDOC ## Creating Semaphore ### Description Creates a new semaphore with a specified initial value. ### Parameters #### Path Parameters * `initialValue` (number) - Required - The initial value of the semaphore. ``` -------------------------------- ### Create Semaphore for Request Limiting Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/configuration.md Example of using Semaphore to limit concurrent web requests. ```typescript // For a web crawler limiting concurrent requests const requestLimiter = new Semaphore(10); // Max 10 concurrent requests ``` -------------------------------- ### Non-blocking Mutex Acquire Example Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Demonstrates how to attempt to acquire a mutex lock without blocking. If the lock is not immediately available, it catches the E_ALREADY_LOCKED error. ```typescript const nonBlockingMutex = tryAcquire(new Mutex()); try { const release = await nonBlockingMutex.acquire(); try { console.log('Lock acquired'); // Critical section } finally { release(); } } catch (error) { if (error === E_ALREADY_LOCKED) { console.log('Could not acquire lock immediately'); } } ``` -------------------------------- ### getValue() and setValue() Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Available only on semaphores. Get and set the semaphore value. ```APIDOC ## getValue() and setValue() ### Description These methods are specific to semaphores wrapped by `tryAcquire`. `getValue()` retrieves the current count of available resources, and `setValue()` allows direct manipulation of this count. ### Methods - `getValue(): number` - `setValue(value: number): void` ### Parameters - **value** (number): The new value to set for the semaphore count. ### Response - **getValue()**: Returns the current semaphore value. - **setValue()**: Does not return a value. ### Example ```typescript const semaphore = tryAcquire(new Semaphore(5)); console.log('Initial value:', semaphore.getValue()); // Output: 5 semaphore.setValue(10); console.log('Updated value:', semaphore.getValue()); // Output: 10 ``` ``` -------------------------------- ### Error Handling Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Details on error conditions, how errors are thrown, and examples of catching errors. ```APIDOC ## Error Handling This section describes the error conditions and how to handle them. ### Error Definitions The library defines specific error types for various failure conditions. ### When Errors Are Thrown Errors are typically thrown when: - A timeout occurs during lock acquisition. - An invalid operation is attempted (e.g., releasing an unacquired lock). ### How to Catch Errors Use standard JavaScript `try...catch` blocks around operations that might throw errors, especially when using timeout or non-blocking features. ### Error Examples ```javascript import { Mutex } from 'async-mutex'; const mutex = new Mutex(); async function example() { try { await mutex.acquire(); // Critical section } catch (error) { console.error('An error occurred:', error.message); } finally { // Ensure release even if error occurs // Note: runExclusive handles this automatically } } ``` ``` -------------------------------- ### Custom Error Handling Examples Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/errors.md Demonstrates how to pass custom error objects for cancellation, timeout, and already-locked conditions when using Mutex and Semaphore. ```typescript import { Mutex, Semaphore, withTimeout, tryAcquire } from 'async-mutex'; // Custom cancel error const mutex = new Mutex(new Error('Custom cancel')); // Custom semaphore cancel error const semaphore = new Semaphore(3, new Error('Custom cancel')); // Custom timeout error const timedMutex = withTimeout( new Mutex(), 5000, new Error('Custom timeout') ); // Custom already-locked error const nonBlockingMutex = tryAcquire( new Mutex(), new Error('Custom already-locked') ); ``` -------------------------------- ### Non-blocking Mutex WaitForUnlock Example Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Illustrates how to check if a mutex is available without blocking. The promise rejects immediately if the lock is already held. ```typescript const nonBlockingMutex = tryAcquire(new Mutex()); try { await nonBlockingMutex.waitForUnlock(); console.log('Lock is available now'); } catch (error) { if (error === E_ALREADY_LOCKED) { console.log('Lock is not currently available'); } } ``` -------------------------------- ### Generic Worker Type Examples Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/types.md Illustrates the use of the generic type parameter T in Worker for type-safe callback functions returning strings or numbers. ```typescript // Worker that returns a string const stringWorker: MutexInterface.Worker = () => 'hello'; const result: Promise = mutex.runExclusive(stringWorker); // Worker that returns a number const numberWorker: SemaphoreInterface.Worker = (value) => value * 2; const result: Promise = semaphore.runExclusive(numberWorker); ``` -------------------------------- ### Semaphore for Concurrency Control Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/README.md Illustrates how to use a Semaphore to limit the number of concurrent operations. This is useful for managing external resources like API rate limits or database connections. The example fetches multiple URLs concurrently, ensuring no more than 5 requests are active at once. ```typescript import { Semaphore } from 'async-mutex'; const semaphore = new Semaphore(5); // Max 5 concurrent operations const results = await Promise.all( urls.map(url => semaphore.runExclusive(() => fetchUrl(url)) ) ); ``` -------------------------------- ### Get Current Value Source: https://github.com/dirtyhairy/async-mutex/blob/master/API.md Retrieves the current numerical value of the semaphore. ```typescript const value = semaphore.getValue(); ``` -------------------------------- ### Basic Mutex Usage with runExclusive and acquire/release Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/README.md Demonstrates two primary ways to use a Mutex: `runExclusive` for automatic acquire/release and manual `acquire`/`release` for more control. Use `runExclusive` for simpler cases and manual control when complex error handling or conditional release is needed. ```typescript import { Mutex } from 'async-mutex'; const mutex = new Mutex(); // Using runExclusive const result = await mutex.runExclusive(async () => { return await criticalOperation(); }); // Using acquire/release const release = await mutex.acquire(); try { await criticalOperation(); } finally { release(); } ``` -------------------------------- ### Get Current Semaphore Value Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/Semaphore.md Retrieve the current counter value of the semaphore. This can be used for monitoring or debugging purposes. ```typescript const value = semaphore.getValue(); console.log('Semaphore value:', value); ``` -------------------------------- ### API Reference - Utility Functions Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Documentation for utility functions like `withTimeout` and `tryAcquire`. ```APIDOC ## Utility Functions Provides utility functions for enhancing lock management. ### `withTimeout(promise: Promise, ms: number, timeoutError?: Error): Promise` Wraps a Promise with a timeout. If the Promise does not resolve or reject within the specified milliseconds, it will be rejected with the provided `timeoutError` or a default timeout error. #### Parameters - **promise** (Promise) - Required - The Promise to wrap. - **ms** (number) - Required - The timeout duration in milliseconds. - **timeoutError** (Error) - Optional - The error to throw on timeout. - **Returns**: `Promise` - The original Promise, or a rejected Promise if a timeout occurs. ### `tryAcquire(mutex: Mutex | Semaphore): Promise` Attempts to acquire a lock or semaphore permit without blocking. Returns the result of the `runExclusive` callback if successful, or `undefined` if the lock/permit could not be acquired immediately. #### Parameters - **mutex** (Mutex | Semaphore) - Required - The Mutex or Semaphore instance to attempt to acquire. - **callback** (function) - Required - The function to execute if the lock/permit is acquired. - **Returns**: `Promise` - The result of the callback if acquired, otherwise `undefined`. ``` -------------------------------- ### Wait for Semaphore Unlock (Promise Style) Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Use `waitForUnlock` to get a promise that resolves when the semaphore can be acquired again. This operation does not lock the semaphore. ```typescript semaphore .waitForUnlock() .then(() => { // ... }); ``` -------------------------------- ### API Reference - Semaphore Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Detailed documentation for the Semaphore class, including its constructor, methods, parameters, and return types. ```APIDOC ## Semaphore Class Manages a pool of resources with a limited number of concurrent accesses. ### Constructor `new Semaphore(count: number, options?: SemaphoreOptions)` Initializes a new Semaphore instance. #### Parameters - **count** (number) - Required - The maximum number of concurrent accesses allowed. - **options** (SemaphoreOptions) - Optional - Configuration options for the Semaphore. - `delay` (number) - Optional - The delay in milliseconds between retry attempts. - `maxRetries` (number) - Optional - The maximum number of retry attempts. - `onTimeout` (function) - Optional - A callback function executed when a timeout occurs. ### Methods #### `acquire(): Promise` Acquires a permit from the semaphore. Returns a Promise that resolves with a `release` function. - **Returns**: `Promise` - A Promise that resolves with a function to release the permit. #### `runExclusive(callback: (release: ReleaseFn) => Promise | T): Promise` Acquires a permit, executes the provided callback, and releases the permit. #### Parameters - **callback** (function) - Required - The function to execute while the permit is held. - `release` (ReleaseFn) - The function to release the permit. - **Returns**: `Promise` - The result of the callback function. #### `isLocked(): boolean` Checks if the semaphore has any permits available (i.e., if it is not fully utilized). - **Returns**: `boolean` - `true` if permits are available, `false` otherwise. #### `release(): void` Releases a permit back to the semaphore. This method should typically be called by the function returned from `acquire` or within `runExclusive`. ``` -------------------------------- ### Semaphore Constructor Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/Semaphore.md Initializes a new Semaphore instance. You can set the initial count of available resources and an optional custom error to be thrown when pending requests are canceled. ```APIDOC ## new Semaphore(initialValue, cancelError) ### Description Creates a new semaphore with the specified initial value. ### Parameters #### Path Parameters * None #### Query Parameters * None #### Request Body * None ### Constructor Signature ```typescript new Semaphore(initialValue: number, cancelError?: Error): Semaphore ``` #### Parameters - **initialValue** (number) - Required - The initial counter value (must be a positive integer). - **cancelError** (Error) - Optional - A custom error to be thrown when pending lock requests are canceled. Defaults to `E_CANCELED`. ### Example ```typescript import { Semaphore } from 'async-mutex'; // Allow 3 concurrent operations const semaphore = new Semaphore(3); // With custom cancel error const semaphoreWithCustomError = new Semaphore(5, new Error('Custom cancel')); ``` ``` -------------------------------- ### Timeout Behavior with Multiple Acquisitions Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/configuration.md Illustrates that each acquire operation on a timed mutex has its own independent timeout. The timeout is measured from the start of each operation. ```typescript import { Mutex, withTimeout, E_TIMEOUT } from 'async-mutex'; const mutex = withTimeout(new Mutex(), 1000); // Each of these has its own 1-second timeout const release1 = await mutex.acquire(); // 1000ms timeout const release2 = await mutex.acquire(); // 1000ms timeout (resets after first completes) ``` -------------------------------- ### CommonJS Import Pattern Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/INDEX.md Demonstrates how to import Mutex, Semaphore, and withTimeout using the CommonJS module system, typically used in Node.js environments. ```javascript const { Mutex, Semaphore, withTimeout } = require('async-mutex'); ``` -------------------------------- ### Import Mutex, Semaphore, and utilities Source: https://github.com/dirtyhairy/async-mutex/blob/master/API.md Import necessary components from the async-mutex library for CommonJS, ES6, and TypeScript environments. ```javascript // CommonJS const { Mutex, Semaphore, withTimeout, tryAcquire } = require('async-mutex'); ``` ```javascript // ES6 import { Mutex, Semaphore, withTimeout, tryAcquire } from 'async-mutex'; ``` ```typescript // TypeScript import { Mutex, MutexInterface, Semaphore, SemaphoreInterface, withTimeout, tryAcquire, E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED } from 'async-mutex'; ``` -------------------------------- ### API Reference - Mutex Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Detailed documentation for the Mutex class, including its constructor, methods, parameters, and return types. ```APIDOC ## Mutex Class Provides mutual exclusion for asynchronous operations. ### Constructor `new Mutex(options?: MutexOptions)` Initializes a new Mutex instance. #### Parameters - **options** (MutexOptions) - Optional - Configuration options for the Mutex. - `delay` (number) - Optional - The delay in milliseconds between retry attempts when a lock is contended. - `maxRetries` (number) - Optional - The maximum number of retry attempts. - `onTimeout` (function) - Optional - A callback function executed when a timeout occurs. ### Methods #### `acquire(): Promise` Acquires the lock. Returns a Promise that resolves with a `release` function. - **Returns**: `Promise` - A Promise that resolves with a function to release the lock. #### `runExclusive(callback: (release: ReleaseFn) => Promise | T): Promise` Acquires the lock, executes the provided callback, and releases the lock. #### Parameters - **callback** (function) - Required - The function to execute while the lock is held. - `release` (ReleaseFn) - The function to release the lock. - **Returns**: `Promise` - The result of the callback function. #### `isLocked(): boolean` Checks if the mutex is currently locked. - **Returns**: `boolean` - `true` if the mutex is locked, `false` otherwise. #### `release(): void` Releases the lock. This method should typically be called by the function returned from `acquire` or within `runExclusive`. ``` -------------------------------- ### tryAcquire Source: https://github.com/dirtyhairy/async-mutex/blob/master/API.md Decorates a mutex or semaphore to fail immediately if the resource is not available. This provides a non-blocking way to attempt acquiring a lock. ```APIDOC ## tryAcquire Decorates a mutex or semaphore to fail immediately if not available. ### Description This function modifies a mutex or semaphore to attempt acquiring a lock without blocking. If the lock is already held, it fails immediately by throwing an error. ### Parameters - **mutex/semaphore**: The mutex or semaphore instance to decorate. - **customError** (Error, optional): A custom error object to throw if the resource is already locked. Defaults to `E_ALREADY_LOCKED`. ``` -------------------------------- ### tryAcquire() Function Signature Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Demonstrates the function signatures for decorating a Mutex or Semaphore with tryAcquire. It shows how to wrap existing mutexes or semaphores to enable non-blocking acquire operations. ```typescript tryAcquire( mutex: M, alreadyAcquiredError?: Error ): MutexInterface tryAcquire( semaphore: S, alreadyAcquiredError?: Error ): SemaphoreInterface ``` -------------------------------- ### tryAcquire with Semaphore and Retry Logic Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Shows how to use tryAcquire with a Semaphore and implement retry logic for operations that might fail due to the lock being contended. It retries up to a maximum number of attempts with increasing delays. ```typescript import { tryAcquire, E_ALREADY_LOCKED } from 'async-mutex'; const semaphore = tryAcquire(new Semaphore(2)); let retries = 0; const maxRetries = 3; async function processWithRetry() { while (retries < maxRetries) { try { return await semaphore.runExclusive(() => { return fetchAndProcess(); }); } catch (error) { if (error === E_ALREADY_LOCKED) { retries++; await new Promise(r => setTimeout(r, 100 * retries)); } else { throw error; } } } throw new Error('Max retries exceeded'); } ``` -------------------------------- ### Semaphore Class Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/EXPORTS.md The Semaphore class is a counting semaphore used to control concurrent access to multiple resources. It is initialized with a starting value and an optional cancel error. ```APIDOC ## Class Semaphore ### Description Counting semaphore for controlling concurrent access to multiple resources. ### Constructor `new Semaphore(initialValue: number, cancelError?: Error)` ### Methods - `acquire(weight?: number, priority?: number): Promise<[number, SemaphoreInterface.Releaser]>`: Acquires the semaphore with a given weight. Returns a promise resolving to the current value and a releaser function. - `runExclusive(callback: SemaphoreInterface.Worker, weight?: number, priority?: number): Promise`: Runs a callback function exclusively with a given weight. The semaphore is released after the callback completes. - `waitForUnlock(weight?: number, priority?: number): Promise`: Waits until the semaphore is unlocked or the specified weight can be acquired. - `isLocked(): boolean`: Checks if the semaphore is currently locked (i.e., its value is zero). - `getValue(): number`: Gets the current value of the semaphore. - `setValue(value: number): void`: Sets the current value of the semaphore. - `release(weight?: number): void`: Releases the semaphore by the specified weight. - `cancel(): void`: Cancels the semaphore acquisition. ``` -------------------------------- ### Decorate Mutex and Semaphore with Timeout Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/withTimeout.md Use withTimeout to wrap Mutex or Semaphore instances. Specify the timeout duration in milliseconds. This example shows decorating both a mutex and a semaphore. ```typescript import { Mutex, Semaphore, withTimeout, E_TIMEOUT } from 'async-mutex'; // Decorate a mutex with 5-second timeout const mutex = new Mutex(); const mutexWithTimeout = withTimeout(mutex, 5000); // Decorate a semaphore with 100ms timeout const semaphore = new Semaphore(3); const semaphoreWithTimeout = withTimeout(semaphore, 100); ``` -------------------------------- ### Try Acquire Mutex/Semaphore (Async/Await) Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Use `tryAcquire` with async/await for immediate lock acquisition attempts. Catches `E_ALREADY_LOCKED` if the resource is not available. ```typescript import {tryAcquire, E_ALREADY_LOCKED} from 'async-mutex'; try { await tryAcquire(semaphoreOrMutex).runExclusive(() => { // ... }); } catch (e) { if (e === E_ALREADY_LOCKED) { // ... } } ``` -------------------------------- ### Import Mutex, Semaphore, and utilities (ES6) Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/README.md Import necessary components from the async-mutex library using ES6 module syntax. This is suitable for modern JavaScript environments. ```javascript import { Mutex, Semaphore, withTimeout, tryAcquire } from 'async-mutex'; ``` -------------------------------- ### Cancel pending locks (Promise style) Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Cancels all pending locks on the semaphore, rejecting their promises with E_CANCELED. Currently held locks are not affected. This example shows how to catch the cancellation error. ```typescript import {E_CANCELED} from 'async-mutex'; semaphore .runExclusive(() => { // ... }) .then(() => { // ... }) .catch(e => { if (e === E_CANCELED) { // ... } }); ``` -------------------------------- ### Create a Mutex Instance Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/Mutex.md Instantiate a Mutex. You can optionally provide a custom error to be thrown when pending lock requests are canceled. ```typescript import { Mutex } from 'async-mutex'; const mutex = new Mutex(); // With custom cancel error const mutexWithCustomError = new Mutex(new Error('Custom cancel error')); ``` -------------------------------- ### Importing async-mutex in Node.js Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/configuration.md Demonstrates how to import the library in Node.js using either CommonJS or ES Modules syntax. Ensure your Node.js version supports ES Modules if you choose that option. ```typescript // CommonJS (Node.js) const { Mutex, Semaphore, withTimeout, tryAcquire } = require('async-mutex'); // ES Modules (Node.js 12.16+, 13.7+) import { Mutex, Semaphore, withTimeout, tryAcquire } from 'async-mutex'; ``` -------------------------------- ### Constructor Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/Mutex.md Creates a new Mutex instance. Optionally accepts a custom error to be thrown when pending lock requests are canceled. ```APIDOC ## new Mutex ### Description Creates a new mutex instance. Optionally accepts a custom error to be thrown when pending lock requests are canceled. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method Signature ```typescript new Mutex(cancelError?: Error): Mutex ``` ### Parameters - **cancelError** (Error) - Optional - Custom error thrown when pending lock requests are canceled. Defaults to `E_CANCELED`. ### Example ```typescript import { Mutex } from 'async-mutex'; const mutex = new Mutex(); // With custom cancel error const mutexWithCustomError = new Mutex(new Error('Custom cancel error')); ``` ``` -------------------------------- ### Import All Exports Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/INDEX.md Imports all available exports from the 'async-mutex' library at once. This is a convenient way to access all features but may not be optimal for tree-shaking. ```typescript import { Mutex, Semaphore, MutexInterface, SemaphoreInterface, withTimeout, tryAcquire, E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED } from 'async-mutex'; ``` -------------------------------- ### Import Mutex, Semaphore, and utilities (TypeScript) Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/README.md Import necessary components and types from the async-mutex library using TypeScript syntax. This includes interfaces and error codes. ```typescript import { Mutex, MutexInterface, Semaphore, SemaphoreInterface, withTimeout, tryAcquire, E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED } from 'async-mutex'; ``` -------------------------------- ### Semaphore Constructor Source: https://github.com/dirtyhairy/async-mutex/blob/master/API.md Initializes a new Semaphore instance with a given initial value and an optional custom cancel error. ```APIDOC ## Semaphore Constructor A counting semaphore for controlling access to multiple resources. ### Constructor ```typescript const semaphore = new Semaphore(initialValue: number, cancelError?: Error); ``` - `initialValue`: Initial value of the semaphore (positive integer) - `cancelError`: Optional custom error used when canceling pending locks (default: `E_CANCELED`) ``` -------------------------------- ### release Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Releases the semaphore, optionally by a specified weight. This is an unscoped release and requires manual weight management if not using the release function from `acquire`. ```APIDOC ## release ### Description Releases the semaphore, optionally incrementing it by a specified weight. This is an unscoped release. ### Method `release(weight?: number): void ### Parameters #### Path Parameters * `weight` (number) - Optional - The value to increment the semaphore by. Defaults to 1 if not provided. ``` -------------------------------- ### Importing Mutex with ES6 Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Use this snippet to import Mutex, Semaphore, and withTimeout using ES6 style imports. ```javascript import {Mutex, Semaphore, withTimeout} from 'async-mutex'; ``` -------------------------------- ### Try Acquire Mutex/Semaphore (Promise Style) Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Use `tryAcquire` to attempt acquiring a lock immediately. If the lock is unavailable, it rejects with `E_ALREADY_LOCKED`. ```typescript import {tryAcquire, E_ALREADY_LOCKED} from 'async-mutex'; tryAcquire(semaphoreOrMutex) .runExclusive(() => { // ... }) .then(() => { // ... }) .catch(e => { if (e === E_ALREADY_LOCKED) { // ... } }); ``` -------------------------------- ### Semaphore Class Reference Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Provides a complete reference for the Semaphore class, including its constructor, methods for acquiring and releasing resources, and managing the semaphore's value. ```APIDOC ## Semaphore Class ### Description Reference for the Semaphore class, detailing its constructor and methods for managing concurrent access with a specified limit. ### Methods - **Constructor**: Initializes a new Semaphore instance with a given initial value and optional configuration. - **acquire(weight?: number)**: Acquires resources from the semaphore. Accepts an optional `weight` parameter. Returns a Promise that resolves with a `release` function when the resources are acquired. - **runExclusive(callback: (release: () => void) => Promise | T, weight?: number)**: Acquires resources, executes the provided callback, and releases the resources. Accepts an optional `weight` parameter. Returns the result of the callback. - **release(weight?: number)**: Releases resources back to the semaphore. Accepts an optional `weight` parameter. - **getValue()**: Returns the current value (available resources) of the semaphore. - **setValue(value: number)**: Sets the current value of the semaphore. - **waitForUnlock(weight?: number)**: Returns a Promise that resolves when the semaphore's value is sufficient for the given `weight` (defaults to 1). - **isLocked()**: Returns `true` if the semaphore is currently in use (value is less than its initial capacity), `false` otherwise. - **cancel()**: Cancels any pending resource acquisition requests. ``` -------------------------------- ### Core Features Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Documentation for the core features of the async-mutex library, including binary locking, semaphore counting, priority scheduling, custom error handling, and timeout/non-blocking decorators. ```APIDOC ## Core Features This section outlines the fundamental capabilities provided by the async-mutex library. ### Mutex Binary Locking Provides exclusive access to a shared resource. ### Semaphore Counting Locks Allows a specified number of concurrent accesses to a resource. ### Priority-Based Scheduling Enables tasks with higher priority to acquire locks before lower-priority tasks. ### Custom Error Handling Supports defining custom error types and handling strategies. ### Timeout Decorator Allows setting a maximum time to wait for a lock, with fallback options. ### Non-blocking Decorator Enables attempting to acquire a lock without blocking, returning immediately if unavailable. ### Weighted Semaphore Operations Supports semaphores where acquiring a lock may consume a specified weight. ### Lock Cancellation Provides mechanisms to cancel pending lock acquisition requests. ``` -------------------------------- ### runExclusive() Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/Semaphore.md Executes a given callback function after acquiring the semaphore. The semaphore is automatically released once the callback completes, ensuring resource safety. ```APIDOC ## runExclusive(callback, weight, priority) ### Description Executes a callback function with the semaphore acquired. The callback receives the current semaphore value before acquisition. The semaphore is automatically released when the callback completes. ### Method `runExclusive` ### Parameters #### Path Parameters * None #### Query Parameters * None #### Request Body * None #### Parameters - **callback** ((value: number) => Promise | T) - Required - The function to execute with the semaphore acquired. It receives the semaphore's value before acquisition. - **weight** (number) - Optional - The amount to decrement the semaphore by. Defaults to 1. Must be a positive integer. - **priority** (number) - Optional - The priority for scheduling lock acquisition. Higher values execute first. Defaults to 0. ### Returns * **Promise** - A promise that adopts the state of the callback's return value. ### Throws * `E_CANCELED` (or custom error) if the semaphore is canceled while waiting. * Any error thrown by the callback is propagated. ### Example ```typescript const result = await semaphore.runExclusive(async (value) => { console.log('Semaphore value at acquisition:', value); return await processWithConstraint(); }); // With weight const result = await semaphore.runExclusive(async (value) => { // Uses 2 units return value; }, 2); // With priority const result = await semaphore.runExclusive((value) => { return compute(value); }, 1, 10); ``` ``` -------------------------------- ### Acquire Semaphore (Async/Await) Source: https://github.com/dirtyhairy/async-mutex/blob/master/API.md Acquires the semaphore using async/await. The critical section should be placed within a try...finally block to ensure release is always called. ```typescript // Async/await style const [value, release] = await semaphore.acquire(); try { // Critical section using value } finally { release(); } ``` -------------------------------- ### Create Semaphore Instance Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/Semaphore.md Instantiate a new Semaphore with an initial counter value. Optionally, provide a custom error to be thrown when pending lock requests are canceled. ```typescript import { Semaphore } from 'async-mutex'; // Allow 3 concurrent operations const semaphore = new Semaphore(3); // With custom cancel error const semaphoreWithCustomError = new Semaphore(5, new Error('Custom cancel')); ``` -------------------------------- ### Mutex with Timeout and Fallback Strategy Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/README.md Shows how to implement a timeout for acquiring a mutex lock. If the lock cannot be acquired within the specified time (5000ms), an error is caught, and a fallback operation is executed. This prevents indefinite waiting for a resource. ```typescript import { Mutex, withTimeout, E_TIMEOUT } from 'async-mutex'; const mutex = withTimeout(new Mutex(), 5000); try { await mutex.acquire(); } catch (error) { if (error === E_TIMEOUT) { // Use fallback strategy return await operationWithoutLock(); } } ``` -------------------------------- ### runExclusive Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Schedules a callback to be executed when the semaphore is available. The callback receives the current semaphore value and the semaphore is released after execution. It supports optional weight and priority arguments. ```APIDOC ## runExclusive ### Description Executes a callback function exclusively once the semaphore is available. The semaphore is automatically released after the callback completes or rejects. Supports optional `weight` and `priority` arguments. ### Method `runExclusive(callback: Function, weight?: number, priority?: number): Promise ` ### Parameters #### Path Parameters * `callback` (Function) - Required - The function to execute. * `weight` (number) - Optional - The value to decrement the semaphore by. * `priority` (number) - Optional - The priority of the task. Higher values indicate higher priority. ``` -------------------------------- ### Initialize Application-Level Locks Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/configuration.md Create mutexes and semaphores at the application level to manage access to shared resources like databases or API rate limits. ```typescript import { Mutex, Semaphore } from 'async-mutex'; // Create locks for different resources const dbMutex = new Mutex(); const cacheMutex = new Mutex(); const apiLimiter = new Semaphore(10); // Max 10 concurrent API calls export { dbMutex, cacheMutex, apiLimiter }; ``` -------------------------------- ### runExclusive() Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Attempts to execute a callback with the decorated lock acquired. If the lock is not immediately available, the promise rejects with the already-acquired error and the callback is not executed. ```APIDOC ## runExclusive() ### Description Attempts to execute a callback function exclusively after acquiring the decorated lock. If the lock cannot be acquired immediately, the operation is skipped and an error is thrown. ### Method - Mutex version: `runExclusive(callback: () => Promise | T, priority?: number): Promise` - Semaphore version: `runExclusive(callback: (value: number) => Promise | T, weight?: number, priority?: number): Promise` ### Parameters - **callback**: The function to execute. For Semaphore, it receives the current semaphore value. - **weight** (number, optional): For Semaphore, specifies the resources to acquire for the callback execution. - **priority** (number, optional): Specifies the priority of the lock acquisition request. ### Response - **Success Response**: A promise that resolves with the return value of the callback function. - **Error Response**: Rejects immediately with an `E_ALREADY_LOCKED` error if the lock is not available. ### Example ```typescript const nonBlockingSemaphore = tryAcquire(new Semaphore(1)); try { const result = await nonBlockingSemaphore.runExclusive(async (value) => { console.log('Executing with value:', value); return await performWork(); }); } catch (error) { if (error === E_ALREADY_LOCKED) { console.log('Could not acquire lock, skipping operation'); } } ``` ``` -------------------------------- ### acquire() Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/api-reference/tryAcquire.md Attempts to acquire the decorated lock. If the lock is immediately available, it is acquired and the promise resolves normally. If the lock is not available, the promise rejects immediately with the already-acquired error. ```APIDOC ## acquire() ### Description Attempts to acquire the decorated lock without blocking. If the lock is available, it resolves with a release function. If not, it rejects immediately. ### Method - Mutex version: `acquire(priority?: number): Promise<() => void>` - Semaphore version: `acquire(weight?: number, priority?: number): Promise<[number, () => void]>` ### Parameters - **priority** (number, optional): For Mutex and Semaphore, specifies the priority of the acquisition request. - **weight** (number, optional): For Semaphore, specifies the number of resources to acquire. ### Response - **Success Response**: A promise that resolves with a `release` function if the lock is acquired. - **Error Response**: Rejects immediately with an `E_ALREADY_LOCKED` error if the lock is not available. ### Example ```typescript const nonBlockingMutex = tryAcquire(new Mutex()); try { const release = await nonBlockingMutex.acquire(); try { console.log('Lock acquired'); // Critical section } finally { release(); } } catch (error) { if (error === E_ALREADY_LOCKED) { console.log('Could not acquire lock immediately'); } } ``` ``` -------------------------------- ### Mutex Class Reference Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Provides a complete reference for the Mutex class, including its constructor, methods for acquiring and releasing locks, and checking the lock status. ```APIDOC ## Mutex Class ### Description Reference for the Mutex class, detailing its constructor and methods for managing exclusive locks. ### Methods - **Constructor**: Initializes a new Mutex instance. Accepts an options object for configuration. - **acquire()**: Acquires a lock. Returns a Promise that resolves with a `release` function when the lock is acquired. - **runExclusive(callback: () => Promise | T)**: Acquires a lock, executes the provided callback, and releases the lock. Returns the result of the callback. - **release()**: Releases the currently held lock. - **waitForUnlock()**: Returns a Promise that resolves when the mutex is no longer locked. - **isLocked()**: Returns `true` if the mutex is currently locked, `false` otherwise. - **cancel()**: Cancels any pending lock acquisition requests. ``` -------------------------------- ### Create Mutex with Default Configuration Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/configuration.md Instantiates a Mutex with the default cancel error. ```typescript import { Mutex } from 'async-mutex'; // Default configuration const mutex1 = new Mutex(); ``` -------------------------------- ### Manual lock acquisition (async/await) Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Acquires the semaphore using async/await, returning the current semaphore value and a release function. The release function must be called in a finally block to ensure the semaphore is freed, even if errors occur. ```typescript const [value, release] = await semaphore.acquire(); try { // ... } finally { release(); } ``` -------------------------------- ### Manual Mutex Acquisition with async/await Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Acquire the mutex using async/await and manually release it within a try...finally block to ensure release even on errors. ```typescript const release = await mutex.acquire(); try { // ... } finally { release(); } ``` -------------------------------- ### Acquire Mutex using async/await Source: https://github.com/dirtyhairy/async-mutex/blob/master/API.md Acquire a mutex and execute a critical section using async/await syntax. Ensure the mutex is released in a finally block. ```typescript // Async/await style const release = await mutex.acquire(); try { // Critical section } finally { release(); } ``` -------------------------------- ### Semaphore with Non-Blocking Try Acquire and Retry Logic Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/README.md Demonstrates a non-blocking approach using `tryAcquire` with a retry mechanism for a Semaphore. If the semaphore is already locked, it waits with exponential backoff before retrying, up to 3 times. This pattern is useful when immediate access is not critical but eventual access is desired. ```typescript import { Semaphore, tryAcquire, E_ALREADY_LOCKED } from 'async-mutex'; const semaphore = tryAcquire(new Semaphore(2)); let retries = 0; while (retries < 3) { try { return await semaphore.runExclusive(() => operation()); } catch (error) { if (error === E_ALREADY_LOCKED) { retries++; await new Promise(r => setTimeout(r, 100 * retries)); } else { throw error; } } } ``` -------------------------------- ### tryAcquire Decorator Reference Source: https://github.com/dirtyhairy/async-mutex/blob/master/_autodocs/DOCUMENTATION_MANIFEST.txt Details the `tryAcquire` decorator, which allows for non-blocking attempts to acquire a lock. ```APIDOC ## tryAcquire Decorator ### Description Provides a non-blocking way to attempt acquiring a lock. If the lock cannot be acquired immediately, it returns `false` instead of waiting. ### Usage ```typescript @tryAcquire(options?: { timeout?: number, error?: Error }) ``` ### Parameters - **options** (object, optional): Configuration options. - **timeout** (number, optional): Maximum time in milliseconds to wait for the lock. If not provided, the acquisition is immediate. - **error** (Error, optional): A custom error to throw if the timeout occurs or if the lock cannot be acquired immediately (when no timeout is specified). ### Supported Methods - `acquire()` - `runExclusive()` ### Behavior When applied to a method, `tryAcquire` attempts to acquire the lock. If successful, it proceeds with the operation. If the lock is unavailable and a `timeout` is specified, it waits up to that duration. If the lock cannot be acquired within the timeout or immediately (if no timeout), it throws the specified or a default error. ``` -------------------------------- ### acquire Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Acquires the semaphore, returning a promise that resolves with the current semaphore value and a release function. The release function must be called to free the semaphore. Supports optional weight and priority arguments. ```APIDOC ## acquire ### Description Acquires the semaphore, returning a promise that resolves with the current semaphore value and a `release` function. The `release` function must be called to free the semaphore. Supports optional `weight` and `priority` arguments. ### Method `acquire(weight?: number, priority?: number): Promise<[number, Function]> ### Parameters #### Path Parameters * `weight` (number) - Optional - The value to decrement the semaphore by. * `priority` (number) - Optional - The priority of the caller. Higher values indicate higher priority. ``` -------------------------------- ### Creating a Mutex Instance Source: https://github.com/dirtyhairy/async-mutex/blob/master/README.md Instantiate a new Mutex object to manage exclusive access to a resource. ```typescript const mutex = new Mutex(); ```