### Install @nds-stack/bun-semaphore Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Install the library using the Bun package manager. ```bash bun add @nds-stack/bun-semaphore ``` -------------------------------- ### available Source: https://github.com/nds-stack/bun-semaphore/blob/main/README.md Gets the current number of available permits in the semaphore. ```APIDOC ## available ### Description Returns the number of currently available permits that can be acquired. ### Property `available` (number) ``` -------------------------------- ### pending Source: https://github.com/nds-stack/bun-semaphore/blob/main/README.md Gets the current number of operations waiting to acquire a permit. ```APIDOC ## pending ### Description Returns the number of operations currently waiting in the queue to acquire a permit. ### Property `pending` (number) ``` -------------------------------- ### acquire Source: https://github.com/nds-stack/bun-semaphore/blob/main/README.md Asynchronously acquires a permit from the semaphore, waiting if necessary. Supports an optional timeout. ```APIDOC ## acquire(timeoutMs?) ### Description Waits for a slot to become available in the semaphore. If a timeout is provided, it will reject if a slot is not acquired within the specified time. ### Method `acquire` ### Parameters #### Query Parameters - **timeoutMs** (number) - Optional - The maximum time in milliseconds to wait for a slot. ``` -------------------------------- ### Initialize and Use Semaphore in Bun Source: https://github.com/nds-stack/bun-semaphore/blob/main/README.md Instantiate a Semaphore with a maximum concurrency limit and use the `withLock` method for automatic acquisition and release of a slot. This is useful for managing concurrent access to resources like database operations. ```typescript import { Semaphore } from "@nds-stack/bun-semaphore"; const db = new Semaphore(5); // max 5 concurrent DB ops await db.withLock(async () => { // only 5 at a time }); ``` -------------------------------- ### Semaphore Constructor Source: https://github.com/nds-stack/bun-semaphore/blob/main/README.md Initializes a new Semaphore instance with a specified maximum concurrency. ```APIDOC ## new Semaphore(maxConcurrency) ### Description Creates a new semaphore instance that limits the number of concurrent operations. ### Parameters #### Path Parameters - **maxConcurrency** (number) - Required - The maximum number of concurrent operations allowed. ``` -------------------------------- ### Monitor Semaphore State with `available`, `pending`, and `size` Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Use the read-only getters `size`, `available`, and `pending` to inspect the current state of a semaphore without modifying it. This is useful for monitoring and implementing backpressure strategies. ```typescript import { Semaphore } from "@nds-stack/bun-semaphore"; const sem = new Semaphore(4); // Acquire 3 slots await Promise.all([sem.acquire(), sem.acquire(), sem.acquire()]); console.log(sem.size); // 4 — maximum configured concurrency (never changes) console.log(sem.available); // 1 — slots still free console.log(sem.pending); // 0 — nobody waiting yet // Queue two extra waiters sem.acquire().catch(() => {}); sem.acquire().catch(() => {}); console.log(sem.available); // 0 — last free slot was claimed console.log(sem.pending); // 1 — one waiter still in queue // Emit a health metric function logSemaphoreHealth(name: string, s: Semaphore) { console.log(`[${name}] size=${s.size} available=${s.available} pending=${s.pending}`); } // [db] size=4 available=0 pending=1 ``` -------------------------------- ### Acquire Semaphore and Execute Callback with `withLock` Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Use `withLock` to acquire a semaphore slot, execute an asynchronous function, and then automatically release the slot. This is equivalent to a try/finally block around `acquire` and `release`. An optional timeout can be provided for acquiring the slot. ```typescript import { Semaphore, SemaphoreError } from "@nds-stack/bun-semaphore"; // Limit DB connection pool to 5 concurrent queries const dbPool = new Semaphore(5); async function queryUser(id: number): Promise<{ id: number; name: string }> { return dbPool.withLock(async () => { // Only 5 of these run at once regardless of how many callers exist const row = await db.query("SELECT id, name FROM users WHERE id = ?", [id]); return row; }); } // Limit outbound API calls to 2 at a time, with a 3-second timeout per slot const apiSem = new Semaphore(2); async function fetchPrice(ticker: string): Promise { try { return await apiSem.withLock(async () => { const res = await fetch(`https://api.example.com/price/${ticker}`); const { price } = await res.json(); return price; }, 3000); } catch (err) { if (err instanceof SemaphoreError) { throw new Error(`Rate limit slot not available for ${ticker}: ${err.message}`); } throw err; } } // Serialize 10 tasks through a single-slot semaphore const serial = new Semaphore(1); const results = await Promise.all( ["AAPL", "GOOG", "MSFT"].map(t => fetchPrice(t)) ); console.log(results); // [192.5, 178.3, 415.0] ``` -------------------------------- ### Initialize Semaphore with Max Concurrency Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Construct a Semaphore instance, specifying the maximum number of concurrent operations allowed. Throws an error for invalid concurrency values. ```typescript import { Semaphore, SemaphoreError } from "@nds-stack/bun-semaphore"; // Allow up to 3 concurrent operations const sem = new Semaphore(3); console.log(sem.size); // 3 — maximum concurrency console.log(sem.available); // 3 — slots currently free console.log(sem.pending); // 0 — callers waiting in queue // Invalid construction try { new Semaphore(0); } catch (err) { if (err instanceof SemaphoreError) { console.error(err.message); // "maxConcurrency must be >= 1" } } ``` -------------------------------- ### new Semaphore(maxConcurrency) Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Constructs a semaphore instance that limits the number of concurrent operations. It throws a SemaphoreError if maxConcurrency is less than 1. ```APIDOC ## new Semaphore(maxConcurrency) ### Description Constructs a semaphore that allows at most `maxConcurrency` simultaneous holders. Throws a `SemaphoreError` synchronously if `maxConcurrency` is less than 1. ### Parameters #### Path Parameters - **maxConcurrency** (number) - Required - The maximum number of concurrent operations allowed. ``` -------------------------------- ### withLock Source: https://github.com/nds-stack/bun-semaphore/blob/main/README.md A convenience method that automatically acquires a permit before executing a function and releases it afterward. Supports an optional timeout for acquisition. ```APIDOC ## withLock(fn, timeoutMs?) ### Description Acquires a lock, executes the provided asynchronous function `fn`, and then automatically releases the lock. This ensures the lock is always released, even if `fn` throws an error. Supports an optional timeout for the initial acquisition. ### Method `withLock` ### Parameters #### Path Parameters - **fn** (Function) - Required - The asynchronous function to execute while holding the lock. #### Query Parameters - **timeoutMs** (number) - Optional - The maximum time in milliseconds to wait for the lock to be acquired before executing `fn`. ``` -------------------------------- ### semaphore.acquire(timeoutMs?) Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Acquires a slot from the semaphore. It returns a Promise that resolves when a slot is available or rejects if a timeout occurs. ```APIDOC ## semaphore.acquire(timeoutMs?) ### Description Acquires one slot from the semaphore, returning a `Promise` that resolves immediately if a slot is free or waits in FIFO order until one becomes available. The optional `timeoutMs` argument causes the promise to reject with a `SemaphoreError` if the slot is not acquired within that many milliseconds. ### Parameters #### Path Parameters - **timeoutMs** (number) - Optional - The maximum time in milliseconds to wait for a slot to become available. ``` -------------------------------- ### release Source: https://github.com/nds-stack/bun-semaphore/blob/main/README.md Releases a previously acquired permit, allowing another waiting operation to proceed. ```APIDOC ## release() ### Description Releases a permit back to the semaphore, potentially allowing a waiting operation to acquire it. ### Method `release` ``` -------------------------------- ### semaphore.available / semaphore.pending / semaphore.size Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Provides read-only access to the semaphore's current state. `size` indicates the maximum concurrency, `available` shows the number of free slots, and `pending` shows the number of operations waiting for a slot. These getters are useful for monitoring and implementing backpressure strategies. ```APIDOC ## `semaphore.available` / `semaphore.pending` / `semaphore.size` Read-only getters that expose the current state of the semaphore without mutating it. Useful for monitoring, logging, and backpressure decisions. ```typescript import { Semaphore } from "@nds-stack/bun-semaphore"; const sem = new Semaphore(4); // Acquire 3 slots await Promise.all([sem.acquire(), sem.acquire(), sem.acquire()]); console.log(sem.size); // 4 — maximum configured concurrency (never changes) console.log(sem.available); // 1 — slots still free console.log(sem.pending); // 0 — nobody waiting yet // Queue two extra waiters sem.acquire().catch(() => {}); sem.acquire().catch(() => {}); console.log(sem.available); // 0 — last free slot was claimed console.log(sem.pending); // 1 — one waiter still in queue // Emit a health metric function logSemaphoreHealth(name: string, s: Semaphore) { console.log(`[${name}] size=${s.size} available=${s.available} pending=${s.pending}`); } // [db] size=4 available=0 pending=1 ``` ``` -------------------------------- ### semaphore.withLock(fn, timeoutMs?) Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Acquires the semaphore, executes an asynchronous function, and then releases the slot. This method ensures that the critical section is executed safely within the concurrency limits defined by the semaphore. It returns a Promise that resolves with the return value of the executed function and accepts an optional timeout for acquiring the lock. ```APIDOC ## `semaphore.withLock(fn, timeoutMs?)` Acquires the semaphore, executes the async callback `fn`, then unconditionally releases the slot — equivalent to a try/finally around `acquire`/`release`. Returns a `Promise` that resolves to `fn`'s return value. Accepts the same optional `timeoutMs` as `acquire`. ```typescript import { Semaphore, SemaphoreError } from "@nds-stack/bun-semaphore"; // Limit DB connection pool to 5 concurrent queries const dbPool = new Semaphore(5); async function queryUser(id: number): Promise<{ id: number; name: string }> { return dbPool.withLock(async () => { // Only 5 of these run at once regardless of how many callers exist const row = await db.query("SELECT id, name FROM users WHERE id = ?", [id]); return row; }); } // Limit outbound API calls to 2 at a time, with a 3-second timeout per slot const apiSem = new Semaphore(2); async function fetchPrice(ticker: string): Promise { try { return await apiSem.withLock(async () => { const res = await fetch(`https://api.example.com/price/${ticker}`); const { price } = await res.json(); return price; }, 3000); } catch (err) { if (err instanceof SemaphoreError) { throw new Error(`Rate limit slot not available for ${ticker}: ${err.message}`); } throw err; } } // Serialize 10 tasks through a single-slot semaphore const serial = new Semaphore(1); const results = await Promise.all( ["AAPL", "GOOG", "MSFT"].map(t => fetchPrice(t)) ); console.log(results); // [192.5, 178.3, 415.0] ``` ``` -------------------------------- ### semaphore.release() Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Releases a previously acquired slot back to the semaphore, potentially unblocking a waiting operation. ```APIDOC ## semaphore.release() ### Description Releases one previously acquired slot back to the semaphore. If callers are waiting in the queue the oldest waiter (FIFO) is resolved immediately without the slot ever becoming "free"; otherwise the available count is incremented. This method is synchronous and returns `void`. ``` -------------------------------- ### Acquire Semaphore Slot with Optional Timeout Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Acquire a slot, waiting if necessary. Optionally, specify a timeout to prevent indefinite waiting. ```typescript import { Semaphore, SemaphoreError } from "@nds-stack/bun-semaphore"; const sem = new Semaphore(1); // --- Basic manual acquire/release --- await sem.acquire(); console.log(sem.available); // 0 // Simulate work await Bun.sleep(50); sem.release(); console.log(sem.available); // 1 // --- Acquire with timeout --- await sem.acquire(); // take the only slot try { // A second caller times out after 100 ms await sem.acquire(100); } catch (err) { if (err instanceof SemaphoreError) { console.error(err.message); // "Semaphore acquire timed out" } } finally { sem.release(); // always release the first slot } ``` -------------------------------- ### SemaphoreError Source: https://context7.com/nds-stack/bun-semaphore/llms.txt A custom error class that extends the built-in `Error`. It is thrown specifically for invalid semaphore construction arguments or when an acquire operation times out. Catching `SemaphoreError` allows developers to differentiate between semaphore-related failures and other runtime errors. ```APIDOC ## `SemaphoreError` A typed error subclass (extends `Error`) thrown in two situations: invalid construction arguments and acquire timeouts. Catching `SemaphoreError` specifically lets callers distinguish semaphore failures from other runtime errors. ```typescript import { Semaphore, SemaphoreError } from "@nds-stack/bun-semaphore"; async function safeFetch(url: string, sem: Semaphore): Promise { try { return await sem.withLock(async () => { const res = await fetch(url); return res.text(); }, 500); // 500 ms timeout to acquire a slot } catch (err) { if (err instanceof SemaphoreError) { // Semaphore-specific failure — e.g., timeout waiting for a slot console.warn("Semaphore error:", err.message); return ""; } // Re-throw unrelated errors (network failure, JSON parse, etc.) throw err; } } const sem = new Semaphore(2); const html = await safeFetch("https://example.com", sem); ``` ``` -------------------------------- ### Release Semaphore Slot Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Release a previously acquired slot. If callers are waiting, the oldest waiter is immediately unblocked. ```typescript import { Semaphore } from "@nds-stack/bun-semaphore"; const sem = new Semaphore(2); await sem.acquire(); await sem.acquire(); console.log(sem.available); // 0 console.log(sem.pending); // 0 // Queue a waiter const waiting = sem.acquire().then(() => console.log("waiter unblocked")); console.log(sem.pending); // 1 // Releasing one slot directly hands it to the waiting caller sem.release(); await waiting; // logs "waiter unblocked" console.log(sem.pending); // 0 console.log(sem.available); // 0 — slot went straight to the waiter sem.release(); console.log(sem.available); // 1 ``` -------------------------------- ### Handle `SemaphoreError` for Specific Failures Source: https://context7.com/nds-stack/bun-semaphore/llms.txt Catch `SemaphoreError` to distinguish between semaphore-related issues (like timeouts) and other runtime errors. This allows for more specific error handling logic. ```typescript import { Semaphore, SemaphoreError } from "@nds-stack/bun-semaphore"; async function safeFetch(url: string, sem: Semaphore): Promise { try { return await sem.withLock(async () => { const res = await fetch(url); return res.text(); }, 500); // 500 ms timeout to acquire a slot } catch (err) { if (err instanceof SemaphoreError) { // Semaphore-specific failure — e.g., timeout waiting for a slot console.warn("Semaphore error:", err.message); return ""; } // Re-throw unrelated errors (network failure, JSON parse, etc.) throw err; } } const sem = new Semaphore(2); const html = await safeFetch("https://example.com", sem); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.